From 88ab3cce8096d61825e89b0af8c102d0be14a32d Mon Sep 17 00:00:00 2001 From: Admazzola Date: Thu, 10 Oct 2024 15:44:27 -0400 Subject: [PATCH 01/32] adding pause manager --- .../SmartCommitmentForwarder.sol | 26 ++- .../LenderCommitmentGroup_Smart.sol | 193 ++++-------------- packages/contracts/contracts/TellerV2.sol | 72 +------ .../contracts/contracts/TellerV2Storage.sol | 4 +- .../interfaces/IPausableTimestamp.sol | 22 ++ .../interfaces/IProtocolPausingManager.sol | 19 ++ .../pausing/HasProtocolPausingManager.sol | 132 ++++++++++++ .../pausing/ProtocolPausingManager.sol | 105 ++++++++++ .../LenderCommitmentGroup_Smart_Test.sol | 2 +- 9 files changed, 359 insertions(+), 216 deletions(-) create mode 100644 packages/contracts/contracts/interfaces/IPausableTimestamp.sol create mode 100644 packages/contracts/contracts/interfaces/IProtocolPausingManager.sol create mode 100644 packages/contracts/contracts/pausing/HasProtocolPausingManager.sol create mode 100644 packages/contracts/contracts/pausing/ProtocolPausingManager.sol diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol index dade3a7a1..7e5279168 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol @@ -7,6 +7,8 @@ import "../interfaces/ILenderCommitmentForwarder.sol"; import "../interfaces/ISmartCommitmentForwarder.sol"; import "./LenderCommitmentForwarder_G1.sol"; +import "../interfaces/IPausableTimestamp.sol"; + import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; @@ -17,7 +19,8 @@ contract SmartCommitmentForwarder is ExtensionsContextUpgradeable, //this should always be first for upgradeability TellerV2MarketForwarder_G3, PausableUpgradeable, //this does add some storage but AFTER all other storage - ISmartCommitmentForwarder + ISmartCommitmentForwarder, + IPausableTimestamp { event ExercisedSmartCommitment( address indexed smartCommitmentAddress, @@ -209,10 +212,31 @@ contract SmartCommitmentForwarder is * @notice Lets the DAO/owner of the protocol undo a previously implemented emergency stop. */ function unpause() public virtual onlyProtocolPauser whenPaused { + setLastUnpausedAt(); _unpause(); } + function getLastUnpausedAt() + public view + returns (uint256) { + + + return Math.max( + lastUnpausedAt, + IPausableTimestamp(TELLER_V2).getLastUnpausedAt() + ) + ; + + + } + + + function setLastUnpausedAt() internal { + lastUnpausedAt = block.timestamp; + } + + // ----- //Overrides diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol index 64d5843e0..8d479ac7b 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol @@ -38,6 +38,8 @@ import { ILoanRepaymentListener } from "../../../interfaces/ILoanRepaymentListen import { ILoanRepaymentCallbacks } from "../../../interfaces/ILoanRepaymentCallbacks.sol"; import { IEscrowVault } from "../../../interfaces/IEscrowVault.sol"; + +import { IPausableTimestamp } from "../../../interfaces/IPausableTimestamp.sol"; import { ILenderCommitmentGroup } from "../../../interfaces/ILenderCommitmentGroup.sol"; import { Payment } from "../../../TellerV2Storage.sol"; @@ -70,6 +72,7 @@ contract LenderCommitmentGroup_Smart is ILenderCommitmentGroup, ISmartCommitment, ILoanRepaymentListener, + IPausableTimestamp, Initializable, OwnableUpgradeable, PausableUpgradeable @@ -142,6 +145,9 @@ contract LenderCommitmentGroup_Smart is //configured by the owner. If 0 , not used. uint256 public maxPrincipalPerCollateralAmount; + + + uint256 public lastUnpausedAt; event PoolInitialized( @@ -239,7 +245,7 @@ contract LenderCommitmentGroup_Smart is } modifier whenForwarderNotPaused() { - require( PausableUpgradeable(address(SMART_COMMITMENT_FORWARDER)).paused() == false , "Protocol is paused"); + require( PausableUpgradeable(address(SMART_COMMITMENT_FORWARDER)).paused() == false , "Smart Commitment Forwarder is paused"); _; } @@ -433,7 +439,7 @@ contract LenderCommitmentGroup_Smart is uint256 _amount, address _sharesRecipient, uint256 _minSharesAmountOut - ) external whenForwarderNotPaused returns (uint256 sharesAmount_) { + ) external whenForwarderNotPaused whenNotPaused returns (uint256 sharesAmount_) { //transfers the primary principal token from msg.sender into this contract escrow @@ -507,7 +513,7 @@ contract LenderCommitmentGroup_Smart is uint256 _collateralTokenId, uint32 _loanDuration, uint16 _interestRate - ) external onlySmartCommitmentForwarder whenForwarderNotPaused { + ) external onlySmartCommitmentForwarder whenForwarderNotPaused whenNotPaused { require( _collateralTokenAddress == address(collateralToken), @@ -569,7 +575,7 @@ contract LenderCommitmentGroup_Smart is function prepareSharesForWithdraw( uint256 _amountPoolSharesTokens - ) external whenForwarderNotPaused returns (bool) { + ) external whenForwarderNotPaused whenNotPaused returns (bool) { return _prepareSharesForWithdraw(msg.sender, _amountPoolSharesTokens); } @@ -604,7 +610,7 @@ contract LenderCommitmentGroup_Smart is uint256 _amountPoolSharesTokens, address _recipient, uint256 _minAmountOut - ) external whenForwarderNotPaused returns (uint256) { + ) external whenForwarderNotPaused whenNotPaused returns (uint256) { require(poolSharesPreparedToWithdrawForLender[msg.sender] >= _amountPoolSharesTokens,"Shares not prepared for withdraw"); require(poolSharesPreparedTimestamp[msg.sender] <= block.timestamp - withdrawlDelayTimeSeconds,"Shares not prepared for withdraw"); @@ -647,7 +653,7 @@ contract LenderCommitmentGroup_Smart is function liquidateDefaultedLoanWithIncentive( uint256 _bidId, int256 _tokenAmountDifference - ) public whenForwarderNotPaused bidIsActiveForGroup(_bidId) { + ) public whenForwarderNotPaused whenNotPaused bidIsActiveForGroup(_bidId) { //use original principal amount as amountDue @@ -658,9 +664,14 @@ contract LenderCommitmentGroup_Smart is uint256 loanDefaultedTimeStamp = ITellerV2(TELLER_V2) .getLoanDefaultTimestamp(_bidId); + uint256 loanDefaultedOrUnpausedAtTimeStamp = Math.max( + loanDefaultedTimeStamp, + getLastUnpausedAt() + ); + int256 minAmountDifference = getMinimumAmountDifferenceToCloseDefaultedLoan( amountDue, - loanDefaultedTimeStamp + loanDefaultedOrUnpausedAtTimeStamp ); require( @@ -734,6 +745,26 @@ contract LenderCommitmentGroup_Smart is ); } + + function getLastUnpausedAt() + public view + returns (uint256) { + + + return Math.max( + lastUnpausedAt, + IPausableTimestamp(SMART_COMMITMENT_FORWARDER).getLastUnpausedAt() //this counts tellerV2 pausing + ) + ; + + + } + + + function setLastUnpausedAt() internal { + lastUnpausedAt = block.timestamp; + } + function _getAmountOwedForBid(uint256 _bidId ) @@ -816,21 +847,11 @@ contract LenderCommitmentGroup_Smart is function calculateCollateralTokensAmountEquivalentToPrincipalTokens( uint256 principalAmount ) public view virtual returns (uint256 collateralTokensAmountToMatchValue) { - //same concept as zeroforone - // (address token0, ) = _getPoolTokens(); - - //bool principalTokenIsToken0 = (address(principalToken) == token0); - //uint256 pairPriceImmediate = _getUniswapV3TokenPairPrice(0); - + uint256 pairPriceWithTwapFromOracle = UniswapPricingLibrary .getUniswapPriceRatioForPoolRoutes(poolOracleRoutes); - - //uint256 scaledPoolOraclePrice = UniswapPricingLibrary.getUniswapPriceRatioForPoolRoutes( - // poolOracleRoutes - // ).percent(collateralRatio); - - + uint256 principalPerCollateralAmount = maxPrincipalPerCollateralAmount == 0 ? pairPriceWithTwapFromOracle : Math.min( @@ -862,132 +883,7 @@ contract LenderCommitmentGroup_Smart is MathUpgradeable.Rounding.Up ); } - //this result is expanded by UNISWAP_EXPANSION_FACTOR - /* function _getUniswapV3TokenPairPrice(uint32 _twapInterval) - internal - view - returns (uint256) - { - // represents the square root of the price of token1 in terms of token0 - - uint160 sqrtPriceX96 = getSqrtTwapX96(_twapInterval); - - //this output is the price ratio expanded by 1e18 - return _getPriceFromSqrtX96(sqrtPriceX96); - } - - //this result is expanded by UNISWAP_EXPANSION_FACTOR - function _getPriceFromSqrtX96(uint160 _sqrtPriceX96) - internal - pure - returns (uint256 price_) - { - - - - uint256 priceX96 = FullMath.mulDiv(uint256(_sqrtPriceX96), uint256(_sqrtPriceX96), (2**96) ); - - // sqrtPrice is in X96 format so we scale it down to get the price - // Also note that this price is a relative price between the two tokens in the pool - // It's not a USD price - price_ = priceX96; - } - - // ---- TWAP - - function getSqrtTwapX96(uint32 twapInterval) - public - view - returns (uint160 sqrtPriceX96) - { - if (twapInterval == 0) { - // return the current price if twapInterval == 0 - (sqrtPriceX96, , , , , , ) = IUniswapV3Pool(UNISWAP_V3_POOL) - .slot0(); - } else { - uint32[] memory secondsAgos = new uint32[](2); - secondsAgos[0] = twapInterval+1; // from (before) - secondsAgos[1] = 1; // to (now) - - (int56[] memory tickCumulatives, ) = IUniswapV3Pool(UNISWAP_V3_POOL) - .observe(secondsAgos); - - - - int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0]; - int24 arithmeticMeanTick = int24(tickCumulativesDelta / int32(twapInterval)); - //// Always round to negative infinity - if (tickCumulativesDelta < 0 && (tickCumulativesDelta % int32(twapInterval) != 0)) arithmeticMeanTick--; - - sqrtPriceX96 = TickMath.getSqrtRatioAtTick(arithmeticMeanTick); - - - } - } - - - function _getPoolTokens() - internal - view - virtual - returns (address token0, address token1) - { - token0 = IUniswapV3Pool(UNISWAP_V3_POOL).token0(); - token1 = IUniswapV3Pool(UNISWAP_V3_POOL).token1(); - } - - - */ - - - // ----- - - /* - Dev Note: pairPriceWithTwap and pairPriceImmediate are expanded by UNISWAP_EXPANSION_FACTOR - - */ - /* function _getCollateralTokensAmountEquivalentToPrincipalTokens( - uint256 principalTokenAmountValue, - uint256 pairPrice - //uint256 pairPriceImmediate, - // bool principalTokenIsToken0 - ) public pure returns (uint256 collateralTokensAmountToMatchValue) { - collateralTokensAmountToMatchValue = token0ToToken1( - principalTokenAmountValue, - pairPrice //if this is lower, collateral tokens amt will be higher - ); - } - - //note: the price is still expanded by UNISWAP_EXPANSION_FACTOR - function token0ToToken1(uint256 amountToken0, uint256 priceToken1PerToken0) - internal - pure - returns (uint256) - { - return - MathUpgradeable.mulDiv( - amountToken0, - UNISWAP_EXPANSION_FACTOR, - priceToken1PerToken0, - MathUpgradeable.Rounding.Up - ); - } - - //note: the price is still expanded by UNISWAP_EXPANSION_FACTOR - function token1ToToken0(uint256 amountToken1, uint256 priceToken1PerToken0) - internal - pure - returns (uint256) - { - return - MathUpgradeable.mulDiv( - amountToken1, - priceToken1PerToken0, - UNISWAP_EXPANSION_FACTOR, - MathUpgradeable.Rounding.Up - ); - }*/ /* This callback occurs when a TellerV2 repayment happens or when a TellerV2 liquidate happens @@ -999,7 +895,7 @@ contract LenderCommitmentGroup_Smart is address repayer, uint256 principalAmount, uint256 interestAmount - ) external onlyTellerV2 whenForwarderNotPaused { + ) external onlyTellerV2 whenForwarderNotPaused whenNotPaused { //can use principal amt to increment amt paid back!! nice for math . totalPrincipalTokensRepaid += principalAmount; totalInterestCollected += interestAmount; @@ -1019,7 +915,7 @@ contract LenderCommitmentGroup_Smart is If principaltokens get stuck in the escrow vault for any reason, anyone may call this function to move them from that vault in to this contract */ - function withdrawFromEscrowVault ( uint256 _amount ) public whenForwarderNotPaused { + function withdrawFromEscrowVault ( uint256 _amount ) public whenForwarderNotPaused whenNotPaused { address _escrowVault = ITellerV2(TELLER_V2).getEscrowVault(); @@ -1120,14 +1016,15 @@ contract LenderCommitmentGroup_Smart is /** * @notice Lets the DAO/owner of the protocol implement an emergency stop mechanism. */ - function pauseBorrowing() public virtual onlyOwner whenNotPaused { + function pauseLendingPool() public virtual onlyOwner whenNotPaused { _pause(); } /** * @notice Lets the DAO/owner of the protocol undo a previously implemented emergency stop. */ - function unpauseBorrowing() public virtual onlyOwner whenPaused { + function unpauseLendingPool() public virtual onlyOwner whenPaused { + setLastUnpausedAt(); _unpause(); } } diff --git a/packages/contracts/contracts/TellerV2.sol b/packages/contracts/contracts/TellerV2.sol index 1613c4f0d..b09149243 100644 --- a/packages/contracts/contracts/TellerV2.sol +++ b/packages/contracts/contracts/TellerV2.sol @@ -5,6 +5,7 @@ pragma solidity >=0.8.0 <0.9.0; import "./ProtocolFee.sol"; import "./TellerV2Storage.sol"; import "./TellerV2Context.sol"; +import "./pausing/HasProtocolPausingManager.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; @@ -50,7 +51,7 @@ contract TellerV2 is ILoanRepaymentCallbacks, OwnableUpgradeable, ProtocolFee, - PausableUpgradeable, + HasProtocolPausingManager, TellerV2Storage, TellerV2Context { @@ -165,23 +166,6 @@ contract TellerV2 is } - modifier onlyPauser() { - - require( pauserRoleBearer[_msgSender()] || owner() == _msgSender(), "Requires role: Pauser"); - - - _; - } - - - modifier whenLiquidationsNotPaused() { - require(!liquidationsPaused, "Liquidations are paused"); - - _; - } - - - /** Constant Variables **/ uint8 public constant CURRENT_CODE_VERSION = 10; @@ -202,6 +186,7 @@ contract TellerV2 is * @param _lenderCommitmentForwarder The address of the lender commitment forwarder contract. * @param _collateralManager The address of the collateral manager contracts. * @param _lenderManager The address of the lender manager contract for loans on the protocol. + * @param _protocolPausingManager The address of the pausing manager contract for the protocol. */ function initialize( uint16 _protocolFee, @@ -210,11 +195,12 @@ contract TellerV2 is address _lenderCommitmentForwarder, address _collateralManager, address _lenderManager, - address _escrowVault + address _escrowVault, + address _protocolPausingManager ) external initializer { __ProtocolFee_init(_protocolFee); - __Pausable_init(); + //__Pausable_init(); require( _lenderCommitmentForwarder.isContract(), @@ -242,6 +228,7 @@ contract TellerV2 is _setLenderManager(_lenderManager); _setEscrowVault(_escrowVault); + __HasProtocolPausingManager_init(_protocolPausingManager, _msgSender()); } /* function setEscrowVault(address _escrowVault) external reinitializer(9) { @@ -703,50 +690,7 @@ contract TellerV2 is ); } - /** - * @notice Lets a pauser of the protocol implement an emergency stop mechanism. - */ - function pauseProtocol() public virtual onlyPauser whenNotPaused { - _pause(); - } - - /** - * @notice Lets a pauser of the protocol undo a previously implemented emergency stop. - */ - function unpauseProtocol() public virtual onlyPauser whenPaused { - _unpause(); - } - - - /** - * @notice Lets a pauser of the protocol implement an emergency stop mechanism. - */ - function pauseLiquidations() public virtual onlyPauser { - liquidationsPaused = true; - } - - /** - * @notice Lets a pauser of the protocol undo a previously implemented emergency stop. - */ - function unpauseLiquidations() public virtual onlyPauser { - liquidationsPaused = false; - } - - - - function addPauser(address _pauser) public virtual onlyOwner { - pauserRoleBearer[_pauser] = true; - } - - - function removePauser(address _pauser) public virtual onlyOwner { - pauserRoleBearer[_pauser] = false; - } - - - function isPauser(address _account) public view returns(bool){ - return pauserRoleBearer[_account] ; - } + function lenderCloseLoan(uint256 _bidId) diff --git a/packages/contracts/contracts/TellerV2Storage.sol b/packages/contracts/contracts/TellerV2Storage.sol index bbbe88527..9dda615e3 100644 --- a/packages/contracts/contracts/TellerV2Storage.sol +++ b/packages/contracts/contracts/TellerV2Storage.sol @@ -163,8 +163,8 @@ abstract contract TellerV2Storage_G6 is TellerV2Storage_G5 { } abstract contract TellerV2Storage_G7 is TellerV2Storage_G6 { - mapping(address => bool) public pauserRoleBearer; - bool public liquidationsPaused; + mapping(address => bool) public _reserved_G7_0 ;//pauserRoleBearer; + bool public _reserved_G7_1; //liquidations paused } abstract contract TellerV2Storage is TellerV2Storage_G7 {} diff --git a/packages/contracts/contracts/interfaces/IPausableTimestamp.sol b/packages/contracts/contracts/interfaces/IPausableTimestamp.sol new file mode 100644 index 000000000..e3b8f4d90 --- /dev/null +++ b/packages/contracts/contracts/interfaces/IPausableTimestamp.sol @@ -0,0 +1,22 @@ + + + + + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + + +//records the unpause timestamp s +interface IPausableTimestamp { + + + function getLastUnpausedAt() + external view + returns (uint256) ; + + // function setLastUnpausedAt() internal; + + + +} diff --git a/packages/contracts/contracts/interfaces/IProtocolPausingManager.sol b/packages/contracts/contracts/interfaces/IProtocolPausingManager.sol new file mode 100644 index 000000000..51736e529 --- /dev/null +++ b/packages/contracts/contracts/interfaces/IProtocolPausingManager.sol @@ -0,0 +1,19 @@ + + + + + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + + +//records the unpause timestamp s +interface IPausableTimestamp { + + + + // function setLastUnpausedAt() internal; + + + +} diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol new file mode 100644 index 000000000..4e2b683a1 --- /dev/null +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) + +pragma solidity ^0.8.0; + + + + +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; +abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable { + + + bool private _reserved0;// _paused.. Deprecated + + address private _protocolPausingManager; + + + + + + + modifier onlyPauserRoleOrOwner() { + + require( pauserRoleBearer[_msgSender()] || owner() == _msgSender(), "Requires role: Pauser"); + + + _; + } + + + modifier whenLiquidationsNotPaused() { + require(!liquidationsPaused, "Liquidations are paused"); + + _; + } + + //rename to when protocol not paused ? + modifier whenNotPaused() { + _requireNotPaused(); + _; + } + + + + + function __HasProtocolPausingManager_init(address protocolPausingManager, address newOwner) internal onlyInitializing { + _protocolPausingManager == protocolPausingManager ; + OwnableUpgradeable(_protocolPausingManager).__Ownable_init(); + OwnableUpgradeable(_protocolPausingManager).transferOwnership(newOwner); + } + + + function getProtocolPausingManager() public view returns (address){ + + return _protocolPausingManager; + } + + + + + + + /* + + + function pauseProtocol() public virtual onlyPauser whenNotPaused { + _pause(); + } + + + function unpauseProtocol() public virtual onlyPauser whenPaused { + _unpause(); + } + + + + function pauseLiquidations() public virtual onlyPauser { + liquidationsPaused = true; + } + + function unpauseLiquidations() public virtual onlyPauser { + liquidationsPaused = false; + } + + + + function addPauser(address _pauser) public virtual onlyOwner { + pauserRoleBearer[_pauser] = true; + } + + + function removePauser(address _pauser) public virtual onlyOwner { + pauserRoleBearer[_pauser] = false; + } + + + function isPauser(address _account) public view returns(bool){ + return pauserRoleBearer[_account] ; + } + + */ + + + + + + + + + + + + + + + + + + + + + + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[48] private __gap; +} diff --git a/packages/contracts/contracts/pausing/ProtocolPausingManager.sol b/packages/contracts/contracts/pausing/ProtocolPausingManager.sol new file mode 100644 index 000000000..409cc87a9 --- /dev/null +++ b/packages/contracts/contracts/pausing/ProtocolPausingManager.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) + +pragma solidity ^0.8.0; + + + +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; + +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + +import "./interfaces/IProtocolPausingManager.sol"; + +/** + + TODO: + + Move SCF pausing into here ?? + + + */ +contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProtocolPausingManager { + + + // bool private _protocolPaused; + //bool private _liquidationsPaused; + + u8 private _currentPauseState; //use an enum !!! + + mapping(address => bool) public pauserRoleBearer ; + + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + * + * Requirements: + * + * - The contract must not be paused. + */ + modifier whenNotPaused() { + _requireNotPaused(); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + * + * Requirements: + * + * - The contract must be paused. + */ + modifier whenPaused() { + _requirePaused(); + _; + } + + /** + * @dev Returns true if the contract is paused, and false otherwise. + */ + function paused() public view virtual returns (bool) { + return _paused; + } + + /** + * @dev Throws if the contract is paused. + */ + function _requireNotPaused() internal view virtual { + require(!paused(), "Pausable: paused"); + } + + /** + * @dev Throws if the contract is not paused. + */ + function _requirePaused() internal view virtual { + require(paused(), "Pausable: not paused"); + } + + /** + * @dev Triggers stopped state. + * + * Requirements: + * + * - The contract must not be paused. + */ + function _pause() internal virtual whenNotPaused { + _paused = true; + emit Paused(_msgSender()); + } + + /** + * @dev Returns to normal state. + * + * Requirements: + * + * - The contract must be paused. + */ + function _unpause() internal virtual whenPaused { + _paused = false; + emit Unpaused(_msgSender()); + } + + +} diff --git a/packages/contracts/tests/LenderCommitmentForwarder/extensions/SmartCommitments/LenderCommitmentGroup_Smart_Test.sol b/packages/contracts/tests/LenderCommitmentForwarder/extensions/SmartCommitments/LenderCommitmentGroup_Smart_Test.sol index 7559a1241..ae8a6d290 100644 --- a/packages/contracts/tests/LenderCommitmentForwarder/extensions/SmartCommitments/LenderCommitmentGroup_Smart_Test.sol +++ b/packages/contracts/tests/LenderCommitmentForwarder/extensions/SmartCommitments/LenderCommitmentGroup_Smart_Test.sol @@ -75,7 +75,7 @@ contract LenderCommitmentGroup_Smart_Test is Testable { _uniswapV3Factory = new UniswapV3FactoryMock(); _uniswapV3Factory.setPoolMock(address(_uniswapV3Pool)); - + vm.warp(1_000_000); principalToken = new TestERC20Token("wrappedETH", "WETH", 1e24, 18); From ed902a55037c3275558b93f50c3002b2ea38ed8f Mon Sep 17 00:00:00 2001 From: Admazzola Date: Thu, 10 Oct 2024 16:04:04 -0400 Subject: [PATCH 02/32] adding upgradeable storage --- .../SmartCommitmentForwarder.sol | 3 +- .../interfaces/IHasProtocolPausingManager.sol | 18 +++++ .../pausing/HasProtocolPausingManager.sol | 38 ++++----- .../pausing/ProtocolPausingManager.sol | 81 +++++++++++++------ 4 files changed, 89 insertions(+), 51 deletions(-) create mode 100644 packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol index 7e5279168..4b949160c 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol @@ -45,6 +45,7 @@ contract SmartCommitmentForwarder is } uint256 public liquidationProtocolFeePercent; + uint256 internal lastUnpausedAt; constructor(address _protocolAddress, address _marketRegistry) @@ -224,7 +225,7 @@ contract SmartCommitmentForwarder is return Math.max( lastUnpausedAt, - IPausableTimestamp(TELLER_V2).getLastUnpausedAt() + IPausableTimestamp(_tellerV2).getLastUnpausedAt() ) ; diff --git a/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol b/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol new file mode 100644 index 000000000..c89fa86ff --- /dev/null +++ b/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol @@ -0,0 +1,18 @@ + + + + + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + + +//records the unpause timestamp s +interface IPausableTimestamp { + + + function getProtocolPausingManager() external view returns (address); + + + +} diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index 4e2b683a1..c4981b088 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -9,10 +9,15 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; -abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable { + +import "../interfaces/IHasProtocolPausingManager.sol"; + + + +abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable, IHasProtocolPausingManager, IPausableTimestamp { - bool private _reserved0;// _paused.. Deprecated + bool private _reserved0;// _paused.. Deprecated , handled by pausing manager address private _protocolPausingManager; @@ -57,23 +62,21 @@ abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable return _protocolPausingManager; } + function getLastUnpausedAt() + external view + returns (uint256) { + return IPausableTimestamp(_protocolPausingManager).getLastUnpausedAt(); + } - /* - - function pauseProtocol() public virtual onlyPauser whenNotPaused { - _pause(); - } - - function unpauseProtocol() public virtual onlyPauser whenPaused { - _unpause(); - } + /* + function pauseLiquidations() public virtual onlyPauser { @@ -86,19 +89,6 @@ abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable - function addPauser(address _pauser) public virtual onlyOwner { - pauserRoleBearer[_pauser] = true; - } - - - function removePauser(address _pauser) public virtual onlyOwner { - pauserRoleBearer[_pauser] = false; - } - - - function isPauser(address _account) public view returns(bool){ - return pauserRoleBearer[_account] ; - } */ diff --git a/packages/contracts/contracts/pausing/ProtocolPausingManager.sol b/packages/contracts/contracts/pausing/ProtocolPausingManager.sol index 409cc87a9..583e750d3 100644 --- a/packages/contracts/contracts/pausing/ProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/ProtocolPausingManager.sol @@ -11,7 +11,7 @@ import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import "./interfaces/IProtocolPausingManager.sol"; +import "../interfaces/IProtocolPausingManager.sol"; /** @@ -21,15 +21,21 @@ import "./interfaces/IProtocolPausingManager.sol"; */ -contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProtocolPausingManager { +contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProtocolPausingManager , IPausableTimestamp{ - // bool private _protocolPaused; - //bool private _liquidationsPaused; + bool private _protocolPaused; + bool private _liquidationsPaused; + //bool private _liquidityPoolsPaused; - u8 private _currentPauseState; //use an enum !!! - mapping(address => bool) public pauserRoleBearer ; + // u8 private _currentPauseState; //use an enum !!! + + mapping(address => bool) public pauserRoleBearer ; + + + uint256 private lastPausedAt; + uint256 private lastUnpausedAt; /** @@ -59,8 +65,8 @@ contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProt /** * @dev Returns true if the contract is paused, and false otherwise. */ - function paused() public view virtual returns (bool) { - return _paused; + function protocolPaused() public view virtual returns (bool) { + return _protocolPaused; } /** @@ -77,29 +83,52 @@ contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProt require(paused(), "Pausable: not paused"); } - /** - * @dev Triggers stopped state. - * - * Requirements: - * - * - The contract must not be paused. - */ - function _pause() internal virtual whenNotPaused { - _paused = true; + + + + + + function pauseProtocol() public virtual onlyPauser whenNotPaused { + _paused = true; emit Paused(_msgSender()); } - /** - * @dev Returns to normal state. - * - * Requirements: - * - * - The contract must be paused. - */ - function _unpause() internal virtual whenPaused { - _paused = false; + + function unpauseProtocol() public virtual onlyPauser whenPaused { + _paused = false; emit Unpaused(_msgSender()); } + + + + function getLastUnpausedAt() + external view + returns (uint256) { + + return lastUnpausedAt; + + } + + + + + // Role Management + + + function addPauser(address _pauser) public virtual onlyOwner { + pauserRoleBearer[_pauser] = true; + } + + + function removePauser(address _pauser) public virtual onlyOwner { + pauserRoleBearer[_pauser] = false; + } + + + function isPauser(address _account) public view returns(bool){ + return pauserRoleBearer[_account] ; + } + } From 265ea51ec6b69b19b8adefb62185b96d0dddbc49 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 10:20:07 -0400 Subject: [PATCH 03/32] fixing interfaces --- .../SmartCommitmentForwarder.sol | 8 +++++++- .../contracts/interfaces/IHasProtocolPausingManager.sol | 2 +- .../contracts/pausing/HasProtocolPausingManager.sol | 2 +- .../contracts/pausing/ProtocolPausingManager.sol | 8 +++++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol index 4b949160c..4c4870848 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol @@ -12,6 +12,9 @@ import "../interfaces/IPausableTimestamp.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol"; + + import { CommitmentCollateralType, ISmartCommitment } from "../interfaces/ISmartCommitment.sol"; @@ -22,6 +25,9 @@ contract SmartCommitmentForwarder is ISmartCommitmentForwarder, IPausableTimestamp { + + using MathUpgradeable for uint256; + event ExercisedSmartCommitment( address indexed smartCommitmentAddress, address borrower, @@ -223,7 +229,7 @@ contract SmartCommitmentForwarder is returns (uint256) { - return Math.max( + return MathUpgradeable.max( lastUnpausedAt, IPausableTimestamp(_tellerV2).getLastUnpausedAt() ) diff --git a/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol b/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol index c89fa86ff..828f0c77b 100644 --- a/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol +++ b/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol @@ -8,7 +8,7 @@ pragma solidity ^0.8.0; //records the unpause timestamp s -interface IPausableTimestamp { +interface IHasProtocolPausingManager { function getProtocolPausingManager() external view returns (address); diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index c4981b088..2895b747d 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -12,7 +12,7 @@ import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "../interfaces/IHasProtocolPausingManager.sol"; - +import "../interfaces/IPausableTimestamp.sol"; abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable, IHasProtocolPausingManager, IPausableTimestamp { diff --git a/packages/contracts/contracts/pausing/ProtocolPausingManager.sol b/packages/contracts/contracts/pausing/ProtocolPausingManager.sol index 583e750d3..4fce2f95f 100644 --- a/packages/contracts/contracts/pausing/ProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/ProtocolPausingManager.sol @@ -11,6 +11,12 @@ import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + + +import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol"; + + + import "../interfaces/IProtocolPausingManager.sol"; /** @@ -22,7 +28,7 @@ import "../interfaces/IProtocolPausingManager.sol"; */ contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProtocolPausingManager , IPausableTimestamp{ - + using MathUpgradeable for uint256; bool private _protocolPaused; bool private _liquidationsPaused; From 1ca27a67127a72c0357e845c7f3914153f68244a Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 10:55:15 -0400 Subject: [PATCH 04/32] finished draft but tellerv2 is too large --- .../SmartCommitmentForwarder.sol | 4 +- packages/contracts/contracts/TellerV2.sol | 18 +-- .../interfaces/IHasProtocolPausingManager.sol | 1 + .../interfaces/IProtocolPausingManager.sol | 12 +- .../contracts/interfaces/ITellerV2.sol | 2 +- .../pausing/HasProtocolPausingManager.sol | 69 ++++-------- .../pausing/ProtocolPausingManager.sol | 105 ++++++++++++------ 7 files changed, 112 insertions(+), 99 deletions(-) diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol index 4c4870848..883a9730d 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol @@ -9,6 +9,8 @@ import "./LenderCommitmentForwarder_G1.sol"; import "../interfaces/IPausableTimestamp.sol"; +import "../interfaces/IHasProtocolPausingManager.sol"; + import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; @@ -40,7 +42,7 @@ contract SmartCommitmentForwarder is modifier onlyProtocolPauser() { - require( ITellerV2( _tellerV2 ).isPauser(_msgSender()) , "Sender not authorized"); + require( IHasProtocolPausingManager( _tellerV2 ).isPauser(_msgSender()) , "Sender not authorized"); _; } diff --git a/packages/contracts/contracts/TellerV2.sol b/packages/contracts/contracts/TellerV2.sol index b09149243..7024bacfe 100644 --- a/packages/contracts/contracts/TellerV2.sol +++ b/packages/contracts/contracts/TellerV2.sol @@ -228,7 +228,7 @@ contract TellerV2 is _setLenderManager(_lenderManager); _setEscrowVault(_escrowVault); - __HasProtocolPausingManager_init(_protocolPausingManager, _msgSender()); + __HasProtocolPausingManager_init(_protocolPausingManager); } /* function setEscrowVault(address _escrowVault) external reinitializer(9) { @@ -271,7 +271,7 @@ contract TellerV2 is uint16 _APR, string calldata _metadataURI, address _receiver - ) public override whenNotPaused returns (uint256 bidId_) { + ) public override whenProtocolNotPaused returns (uint256 bidId_) { bidId_ = _submitBid( _lendingToken, _marketplaceId, @@ -303,7 +303,7 @@ contract TellerV2 is string calldata _metadataURI, address _receiver, Collateral[] calldata _collateralInfo - ) public override whenNotPaused returns (uint256 bidId_) { + ) public override whenProtocolNotPaused returns (uint256 bidId_) { bidId_ = _submitBid( _lendingToken, _marketplaceId, @@ -465,7 +465,7 @@ contract TellerV2 is external override pendingBid(_bidId, "lenderAcceptBid") - whenNotPaused + whenProtocolNotPaused returns ( uint256 amountToProtocol, uint256 amountToMarketplace, @@ -561,7 +561,7 @@ contract TellerV2 is function claimLoanNFT(uint256 _bidId) external acceptedLoan(_bidId, "claimLoanNFT") - whenNotPaused + whenProtocolNotPaused { // Retrieve bid Bid storage bid = bids[_bidId]; @@ -694,7 +694,7 @@ contract TellerV2 is function lenderCloseLoan(uint256 _bidId) - external whenNotPaused whenLiquidationsNotPaused + external whenProtocolNotPaused whenLiquidationsNotPaused acceptedLoan(_bidId, "lenderClaimCollateral") { Bid storage bid = bids[_bidId]; @@ -710,7 +710,7 @@ contract TellerV2 is function lenderCloseLoanWithRecipient( uint256 _bidId, address _collateralRecipient - ) external whenNotPaused whenLiquidationsNotPaused { + ) external whenProtocolNotPaused whenLiquidationsNotPaused { _lenderCloseLoanWithRecipient(_bidId, _collateralRecipient); } @@ -737,7 +737,7 @@ contract TellerV2 is * @param _bidId The id of the loan to make the payment towards. */ function liquidateLoanFull(uint256 _bidId) - external whenNotPaused whenLiquidationsNotPaused + external whenProtocolNotPaused whenLiquidationsNotPaused acceptedLoan(_bidId, "liquidateLoan") { Bid storage bid = bids[_bidId]; @@ -749,7 +749,7 @@ contract TellerV2 is } function liquidateLoanFullWithRecipient(uint256 _bidId, address _recipient) - external whenNotPaused whenLiquidationsNotPaused + external whenProtocolNotPaused whenLiquidationsNotPaused acceptedLoan(_bidId, "liquidateLoan") { _liquidateLoanFull(_bidId, _recipient); diff --git a/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol b/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol index 828f0c77b..f4450e90c 100644 --- a/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol +++ b/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol @@ -13,6 +13,7 @@ interface IHasProtocolPausingManager { function getProtocolPausingManager() external view returns (address); + function isPauser(address _address) external view returns (bool); } diff --git a/packages/contracts/contracts/interfaces/IProtocolPausingManager.sol b/packages/contracts/contracts/interfaces/IProtocolPausingManager.sol index 51736e529..187167b52 100644 --- a/packages/contracts/contracts/interfaces/IProtocolPausingManager.sol +++ b/packages/contracts/contracts/interfaces/IProtocolPausingManager.sol @@ -8,12 +8,12 @@ pragma solidity ^0.8.0; //records the unpause timestamp s -interface IPausableTimestamp { +interface IProtocolPausingManager { - - - // function setLastUnpausedAt() internal; - - + function isPauser(address _address) external view returns (bool); + function protocolPaused() external view returns (bool); + function liquidationsPaused() external view returns (bool); + + } diff --git a/packages/contracts/contracts/interfaces/ITellerV2.sol b/packages/contracts/contracts/interfaces/ITellerV2.sol index a930167a6..cddb224df 100644 --- a/packages/contracts/contracts/interfaces/ITellerV2.sol +++ b/packages/contracts/contracts/interfaces/ITellerV2.sol @@ -173,5 +173,5 @@ interface ITellerV2 { function getEscrowVault() external view returns(address); - function isPauser(address _account) external view returns(bool); + // function isPauser(address _account) external view returns(bool); } diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index 2895b747d..cb71cd76a 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -5,30 +5,34 @@ pragma solidity ^0.8.0; +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; + + import "../interfaces/IHasProtocolPausingManager.sol"; +import "../interfaces/IProtocolPausingManager.sol"; + import "../interfaces/IPausableTimestamp.sol"; -abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable, IHasProtocolPausingManager, IPausableTimestamp { +abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable, IHasProtocolPausingManager, IPausableTimestamp, OwnableUpgradeable { bool private _reserved0;// _paused.. Deprecated , handled by pausing manager address private _protocolPausingManager; - - - + modifier onlyPauserRoleOrOwner() { - require( pauserRoleBearer[_msgSender()] || owner() == _msgSender(), "Requires role: Pauser"); + require( IProtocolPausingManager(_protocolPausingManager). isPauser(_msgSender()) , "Requires role: Pauser"); _; @@ -36,24 +40,25 @@ abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable modifier whenLiquidationsNotPaused() { - require(!liquidationsPaused, "Liquidations are paused"); + require(! IProtocolPausingManager(_protocolPausingManager). liquidationsPaused(), "Liquidations are paused"); _; } //rename to when protocol not paused ? - modifier whenNotPaused() { - _requireNotPaused(); + modifier whenProtocolNotPaused() { + require(! IProtocolPausingManager(_protocolPausingManager). protocolPaused(), "Liquidations are paused"); + _; } - function __HasProtocolPausingManager_init(address protocolPausingManager, address newOwner) internal onlyInitializing { + function __HasProtocolPausingManager_init(address protocolPausingManager) internal onlyInitializing { _protocolPausingManager == protocolPausingManager ; - OwnableUpgradeable(_protocolPausingManager).__Ownable_init(); - OwnableUpgradeable(_protocolPausingManager).transferOwnership(newOwner); + //OwnableUpgradeable(_protocolPausingManager).__Ownable_init(); + //OwnableUpgradeable(_protocolPausingManager).transferOwnership(newOwner); //effectively same as ownable init } @@ -62,6 +67,12 @@ abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable return _protocolPausingManager; } + + function isPauser(address _address) public view returns (bool){ + + return IProtocolPausingManager(_protocolPausingManager). isPauser(_address) ; + } + function getLastUnpausedAt() external view returns (uint256) { @@ -72,43 +83,7 @@ abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable - - - /* - - - - - function pauseLiquidations() public virtual onlyPauser { - liquidationsPaused = true; - } - function unpauseLiquidations() public virtual onlyPauser { - liquidationsPaused = false; - } - - - - - */ - - - - - - - - - - - - - - - - - - diff --git a/packages/contracts/contracts/pausing/ProtocolPausingManager.sol b/packages/contracts/contracts/pausing/ProtocolPausingManager.sol index 4fce2f95f..9251d8fc3 100644 --- a/packages/contracts/contracts/pausing/ProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/ProtocolPausingManager.sol @@ -19,6 +19,9 @@ import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol"; import "../interfaces/IProtocolPausingManager.sol"; + +import "../interfaces/IPausableTimestamp.sol"; + /** TODO: @@ -42,31 +45,33 @@ contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProt uint256 private lastPausedAt; uint256 private lastUnpausedAt; + + + // Events + event PausedProtocol(address indexed account); + event UnpausedProtocol(address indexed account); + event PausedLiquidations(address indexed account); + event UnpausedLiquidations(address indexed account); + event PauserAdded(address indexed account); + event PauserRemoved(address indexed account); - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - * - * Requirements: - * - * - The contract must not be paused. - */ - modifier whenNotPaused() { - _requireNotPaused(); + + modifier onlyPauser() { + require( isPauser( _msgSender()) ); _; } - /** - * @dev Modifier to make a function callable only when the contract is paused. - * - * Requirements: - * - * - The contract must be paused. - */ - modifier whenPaused() { - _requirePaused(); - _; + + //need to initialize so owner is owner (transfer ownership to safe) + + function initialize( + + ) external initializer { + + __Ownable_init(); + } + /** * @dev Returns true if the contract is paused, and false otherwise. @@ -75,37 +80,65 @@ contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProt return _protocolPaused; } - /** - * @dev Throws if the contract is paused. - */ + + function liquidationsPaused() public view virtual returns (bool) { + return _liquidationsPaused; + } + + + /* function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } - /** - * @dev Throws if the contract is not paused. - */ - function _requirePaused() internal view virtual { + function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } - + */ - function pauseProtocol() public virtual onlyPauser whenNotPaused { - _paused = true; - emit Paused(_msgSender()); + function pauseProtocol() public virtual onlyPauser { + require( _protocolPaused == false); + _protocolPaused = true; + lastPausedAt = block.timestamp; + emit PausedProtocol(_msgSender()); } - function unpauseProtocol() public virtual onlyPauser whenPaused { - _paused = false; - emit Unpaused(_msgSender()); + function unpauseProtocol() public virtual onlyPauser { + + require( _protocolPaused == true); + _protocolPaused = false; + lastUnpausedAt = block.timestamp; + emit UnpausedProtocol(_msgSender()); } + function pauseLiquidations() public virtual onlyPauser { + + require( _liquidationsPaused == false); + _liquidationsPaused = true; + lastPausedAt = block.timestamp; + emit PausedLiquidations(_msgSender()); + } + + function unpauseLiquidations() public virtual onlyPauser { + require( _liquidationsPaused == true); + _liquidationsPaused = false; + lastUnpausedAt = block.timestamp; + emit UnpausedLiquidations(_msgSender()); + } + + function getLastPausedAt() + external view + returns (uint256) { + + return lastPausedAt; + + } function getLastUnpausedAt() @@ -124,16 +157,18 @@ contract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProt function addPauser(address _pauser) public virtual onlyOwner { pauserRoleBearer[_pauser] = true; + emit PauserAdded(_pauser); } function removePauser(address _pauser) public virtual onlyOwner { pauserRoleBearer[_pauser] = false; + emit PauserRemoved(_pauser); } function isPauser(address _account) public view returns(bool){ - return pauserRoleBearer[_account] ; + return pauserRoleBearer[_account] || _account == owner() ; } From f66ae4b041764cc4ae6bc43ae93ea2702ffeb256 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 11:00:41 -0400 Subject: [PATCH 05/32] tellerv2 too large stil --- packages/contracts/contracts/TellerV2.sol | 5 +-- .../pausing/HasProtocolPausingManager.sol | 39 ++++--------------- 2 files changed, 10 insertions(+), 34 deletions(-) diff --git a/packages/contracts/contracts/TellerV2.sol b/packages/contracts/contracts/TellerV2.sol index 7024bacfe..77cabbe75 100644 --- a/packages/contracts/contracts/TellerV2.sol +++ b/packages/contracts/contracts/TellerV2.sol @@ -6,8 +6,7 @@ import "./ProtocolFee.sol"; import "./TellerV2Storage.sol"; import "./TellerV2Context.sol"; import "./pausing/HasProtocolPausingManager.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; @@ -228,7 +227,7 @@ contract TellerV2 is _setLenderManager(_lenderManager); _setEscrowVault(_escrowVault); - __HasProtocolPausingManager_init(_protocolPausingManager); + _setProtocolPausingManager(_protocolPausingManager); } /* function setEscrowVault(address _escrowVault) external reinitializer(9) { diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index cb71cd76a..3f9b4e0f9 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -5,14 +5,8 @@ pragma solidity ^0.8.0; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; - -import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; - -import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; - + import "../interfaces/IHasProtocolPausingManager.sol"; @@ -20,24 +14,16 @@ import "../interfaces/IProtocolPausingManager.sol"; import "../interfaces/IPausableTimestamp.sol"; -abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable, IHasProtocolPausingManager, IPausableTimestamp, OwnableUpgradeable { +abstract contract HasProtocolPausingManager + is + IHasProtocolPausingManager, + IPausableTimestamp { bool private _reserved0;// _paused.. Deprecated , handled by pausing manager address private _protocolPausingManager; - - - - - modifier onlyPauserRoleOrOwner() { - - require( IProtocolPausingManager(_protocolPausingManager). isPauser(_msgSender()) , "Requires role: Pauser"); - - - _; - } - + modifier whenLiquidationsNotPaused() { require(! IProtocolPausingManager(_protocolPausingManager). liquidationsPaused(), "Liquidations are paused"); @@ -51,14 +37,10 @@ abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable _; } + - - - - function __HasProtocolPausingManager_init(address protocolPausingManager) internal onlyInitializing { + function _setProtocolPausingManager(address protocolPausingManager) internal { _protocolPausingManager == protocolPausingManager ; - //OwnableUpgradeable(_protocolPausingManager).__Ownable_init(); - //OwnableUpgradeable(_protocolPausingManager).transferOwnership(newOwner); //effectively same as ownable init } @@ -81,13 +63,8 @@ abstract contract HasProtocolPausingManager is Initializable, ContextUpgradeable } - - - - - /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. From 7ff5a9a44cf8538e9ccfd3d315efaece1a6f0887 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 11:06:44 -0400 Subject: [PATCH 06/32] contract still too large --- .../SmartCommitmentForwarder.sol | 6 +++++- .../interfaces/IHasProtocolPausingManager.sol | 2 +- .../contracts/pausing/HasProtocolPausingManager.sol | 11 +++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol index 883a9730d..ed3c06773 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol @@ -11,6 +11,8 @@ import "../interfaces/IPausableTimestamp.sol"; import "../interfaces/IHasProtocolPausingManager.sol"; +import "../interfaces/IProtocolPausingManager.sol"; + import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; @@ -42,7 +44,9 @@ contract SmartCommitmentForwarder is modifier onlyProtocolPauser() { - require( IHasProtocolPausingManager( _tellerV2 ).isPauser(_msgSender()) , "Sender not authorized"); + + address pausingManager = IHasProtocolPausingManager( _tellerV2 ).getProtocolPausingManager(); + require( IProtocolPausingManager( pausingManager ).isPauser(_msgSender()) , "Sender not authorized"); _; } diff --git a/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol b/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol index f4450e90c..88d917511 100644 --- a/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol +++ b/packages/contracts/contracts/interfaces/IHasProtocolPausingManager.sol @@ -13,7 +13,7 @@ interface IHasProtocolPausingManager { function getProtocolPausingManager() external view returns (address); - function isPauser(address _address) external view returns (bool); + // function isPauser(address _address) external view returns (bool); } diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index 3f9b4e0f9..f11129c49 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -16,8 +16,9 @@ import "../interfaces/IPausableTimestamp.sol"; abstract contract HasProtocolPausingManager is - IHasProtocolPausingManager, - IPausableTimestamp { + IHasProtocolPausingManager + // IPausableTimestamp + { bool private _reserved0;// _paused.. Deprecated , handled by pausing manager @@ -49,8 +50,9 @@ abstract contract HasProtocolPausingManager return _protocolPausingManager; } - - function isPauser(address _address) public view returns (bool){ + + /* + function isPauser(address _address) public view returns (bool){ return IProtocolPausingManager(_protocolPausingManager). isPauser(_address) ; } @@ -62,6 +64,7 @@ abstract contract HasProtocolPausingManager return IPausableTimestamp(_protocolPausingManager).getLastUnpausedAt(); } + */ From 50ce22910854ca77af8c792bd1a62949c70f921e Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 11:11:16 -0400 Subject: [PATCH 07/32] trying to make contract smaller --- .../contracts/pausing/HasProtocolPausingManager.sol | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index f11129c49..a0da8c41f 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -11,14 +11,12 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "../interfaces/IHasProtocolPausingManager.sol"; import "../interfaces/IProtocolPausingManager.sol"; - -import "../interfaces/IPausableTimestamp.sol"; + abstract contract HasProtocolPausingManager is - IHasProtocolPausingManager - // IPausableTimestamp - { + IHasProtocolPausingManager + { bool private _reserved0;// _paused.. Deprecated , handled by pausing manager From f38c6184fc21e8c9c792ea6d882954ce1634430b Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 11:31:48 -0400 Subject: [PATCH 08/32] add --- packages/contracts/contracts/TellerV2.sol | 45 ++++++------------- .../contracts/interfaces/ITellerV2.sol | 2 +- .../pausing/HasProtocolPausingManager.sol | 5 ++- 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/packages/contracts/contracts/TellerV2.sol b/packages/contracts/contracts/TellerV2.sol index 77cabbe75..33b866109 100644 --- a/packages/contracts/contracts/TellerV2.sol +++ b/packages/contracts/contracts/TellerV2.sol @@ -203,25 +203,25 @@ contract TellerV2 is require( _lenderCommitmentForwarder.isContract(), - "LenderCommitmentForwarder must be a contract" + "LCF_ic" ); lenderCommitmentForwarder = _lenderCommitmentForwarder; require( _marketRegistry.isContract(), - "MarketRegistry must be a contract" + "MR_ic" ); marketRegistry = IMarketRegistry(_marketRegistry); require( _reputationManager.isContract(), - "ReputationManager must be a contract" + "RM_ic" ); reputationManager = IReputationManager(_reputationManager); require( _collateralManager.isContract(), - "CollateralManager must be a contract" + "CM_ic" ); collateralManager = ICollateralManager(_collateralManager); @@ -241,13 +241,13 @@ contract TellerV2 is { require( _lenderManager.isContract(), - "LenderManager must be a contract" + "LM_ic" ); lenderManager = ILenderManager(_lenderManager); } function _setEscrowVault(address _escrowVault) internal onlyInitializing { - require(_escrowVault.isContract(), "EscrowVault must be a contract"); + require(_escrowVault.isContract(), "EV_ic"); escrowVault = IEscrowVault(_escrowVault); } @@ -320,7 +320,7 @@ contract TellerV2 is require( validation == true, - "Collateral balance could not be validated" + "C bal NV" ); } @@ -340,11 +340,11 @@ contract TellerV2 is sender ); - require(isVerified, "Not verified borrower"); + require(isVerified, "Borrower NV"); require( marketRegistry.isMarketOpen(_marketplaceId), - "Market is not open" + "Mkt C" ); // Set response bid ID. @@ -415,7 +415,7 @@ contract TellerV2 is revert ActionNotAllowed({ bidId: _bidId, action: "cancelBid", - message: "Only the bid owner can cancel!" + message: "Only the bid owner can cancel!" //this is a TON of storage space }); } _cancelBid(_bidId); @@ -433,7 +433,7 @@ contract TellerV2 is revert ActionNotAllowed({ bidId: _bidId, action: "marketOwnerCancelBid", - message: "Only the market owner can cancel!" + message: "Only the market owner can cancel!" //this is a TON of storage space }); } _cancelBid(_bidId); @@ -785,13 +785,6 @@ contract TellerV2 is false ); - /* - _getCollateralManagerForBid(_bidId).liquidateCollateral( - _bidId, - _recipient - ); - */ - collateralManager.liquidateCollateral(_bidId, _recipient); address liquidator = _msgSenderForMarket(bid.marketplaceId); @@ -1243,10 +1236,7 @@ contract TellerV2 is view returns (PaymentCycleType) { - /* bytes32 bidTermsId = bidMarketTermsId[_bidId]; - if (bidTermsId != bytes32(0)) { - return marketRegistry.getPaymentCycleTypeForTerms(bidTermsId); - }*/ + return bidPaymentCycleType[_bidId]; } @@ -1256,11 +1246,7 @@ contract TellerV2 is view returns (uint32) { - /*bytes32 bidTermsId = bidMarketTermsId[_bidId]; - - if (bidTermsId != bytes32(0)) { - return marketRegistry.getPaymentCycleDurationForTerms(bidTermsId); - }*/ + Bid storage bid = bids[_bidId]; @@ -1272,10 +1258,7 @@ contract TellerV2 is view returns (uint32) { - /* bytes32 bidTermsId = bidMarketTermsId[_bidId]; - if (bidTermsId != bytes32(0)) { - return marketRegistry.getPaymentDefaultDurationForTerms(bidTermsId); - }*/ + return bidDefaultDuration[_bidId]; } diff --git a/packages/contracts/contracts/interfaces/ITellerV2.sol b/packages/contracts/contracts/interfaces/ITellerV2.sol index cddb224df..2d80d14b5 100644 --- a/packages/contracts/contracts/interfaces/ITellerV2.sol +++ b/packages/contracts/contracts/interfaces/ITellerV2.sol @@ -173,5 +173,5 @@ interface ITellerV2 { function getEscrowVault() external view returns(address); - // function isPauser(address _account) external view returns(bool); + // function isPauser(address _account) external view returns(bool); } diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index a0da8c41f..ab4aa8548 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -25,19 +25,20 @@ abstract contract HasProtocolPausingManager modifier whenLiquidationsNotPaused() { - require(! IProtocolPausingManager(_protocolPausingManager). liquidationsPaused(), "Liquidations are paused"); + require(! IProtocolPausingManager(_protocolPausingManager). liquidationsPaused() ); _; } //rename to when protocol not paused ? modifier whenProtocolNotPaused() { - require(! IProtocolPausingManager(_protocolPausingManager). protocolPaused(), "Liquidations are paused"); + require(! IProtocolPausingManager(_protocolPausingManager). protocolPaused() ); _; } + //onlyinitializing? function _setProtocolPausingManager(address protocolPausingManager) internal { _protocolPausingManager == protocolPausingManager ; } From 19f9a15d5713ac22bd22256c2fedb012c05719ec Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 11:40:39 -0400 Subject: [PATCH 09/32] reduced size --- packages/contracts/contracts/TellerV2.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/contracts/contracts/TellerV2.sol b/packages/contracts/contracts/TellerV2.sol index 33b866109..29559398b 100644 --- a/packages/contracts/contracts/TellerV2.sol +++ b/packages/contracts/contracts/TellerV2.sol @@ -145,7 +145,7 @@ contract TellerV2 is */ modifier pendingBid(uint256 _bidId, string memory _action) { if (bids[_bidId].state != BidState.PENDING) { - revert ActionNotAllowed(_bidId, _action, "Bid must be pending"); + revert ActionNotAllowed(_bidId, _action, "Bid not pending"); } _; @@ -158,7 +158,7 @@ contract TellerV2 is */ modifier acceptedLoan(uint256 _bidId, string memory _action) { if (bids[_bidId].state != BidState.ACCEPTED) { - revert ActionNotAllowed(_bidId, _action, "Loan must be accepted"); + revert ActionNotAllowed(_bidId, _action, "Loan not accepted"); } _; @@ -415,7 +415,7 @@ contract TellerV2 is revert ActionNotAllowed({ bidId: _bidId, action: "cancelBid", - message: "Only the bid owner can cancel!" //this is a TON of storage space + message: "Not bid owner" //this is a TON of storage space }); } _cancelBid(_bidId); @@ -433,7 +433,7 @@ contract TellerV2 is revert ActionNotAllowed({ bidId: _bidId, action: "marketOwnerCancelBid", - message: "Only the market owner can cancel!" //this is a TON of storage space + message: "Not market owner" //this is a TON of storage space }); } _cancelBid(_bidId); From 7e6455cce09c506531f0e93ca2a5025369a1bda6 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 11:45:34 -0400 Subject: [PATCH 10/32] fixingtests --- packages/contracts/tests/TellerV2/TellerV2_Override.sol | 7 ++----- packages/contracts/tests/TellerV2/TellerV2_Test.sol | 7 ++++++- .../contracts/tests/integration/IntegrationTestHelpers.sol | 7 ++++++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/contracts/tests/TellerV2/TellerV2_Override.sol b/packages/contracts/tests/TellerV2/TellerV2_Override.sol index 52060e58c..7a47bfceb 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_Override.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_Override.sol @@ -16,10 +16,7 @@ contract TellerV2_Override is TellerV2 { constructor() TellerV2(address(0)) {} - function mock_pause(bool _shouldPause) public { - _shouldPause ? _pause() : _unpause(); - } - + function mock_setBid(uint256 bidId, Bid memory bid) public { bids[bidId] = bid; } @@ -81,7 +78,7 @@ contract TellerV2_Override is TellerV2 { function mock_initialize() public initializer { __ProtocolFee_init(0); - __Pausable_init(); + // __Pausable_init(); } function setMockMsgSenderForMarket(address _sender) public { diff --git a/packages/contracts/tests/TellerV2/TellerV2_Test.sol b/packages/contracts/tests/TellerV2/TellerV2_Test.sol index 962a26f04..51cb794d4 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_Test.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_Test.sol @@ -30,6 +30,7 @@ import { BidState, Payment } from "../../contracts/TellerV2Storage.sol"; import "../../contracts/MetaForwarder.sol"; import { LenderManager } from "../../contracts/LenderManager.sol"; import { EscrowVault } from "../../contracts/EscrowVault.sol"; +import { ProtocolPausingManager } from "../../contracts/pausing/ProtocolPausingManager.sol"; contract TellerV2_Test is Testable { TellerV2User private marketOwner; @@ -80,6 +81,9 @@ contract TellerV2_Test is Testable { EscrowVault escrowVault = new EscrowVault(); escrowVault.initialize(); + ProtocolPausingManager protocolPausingManager = new ProtocolPausingManager(); + protocolPausingManager.initialize(); + // Deploy LenderCommitmentForwarder LenderCommitmentForwarder_G1 lenderCommitmentForwarder = new LenderCommitmentForwarder_G1( address(tellerV2), @@ -94,7 +98,8 @@ contract TellerV2_Test is Testable { address(lenderCommitmentForwarder), address(collateralManager), address(lenderManager), - address(escrowVault) + address(escrowVault), + address(protocolPausingManager) ); // Instantiate users & balances diff --git a/packages/contracts/tests/integration/IntegrationTestHelpers.sol b/packages/contracts/tests/integration/IntegrationTestHelpers.sol index 200d44c7b..8fa4e5892 100644 --- a/packages/contracts/tests/integration/IntegrationTestHelpers.sol +++ b/packages/contracts/tests/integration/IntegrationTestHelpers.sol @@ -11,6 +11,8 @@ import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol"; import { MarketRegistry } from "../../contracts/MarketRegistry.sol"; + +import { ProtocolPausingManager } from "../../contracts/pausing/ProtocolPausingManager.sol"; import { EscrowVault } from "../../contracts/EscrowVault.sol"; import { LenderManager } from "../../contracts/LenderManager.sol"; import { LenderCommitmentForwarder_G3 } from "../../contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_G3.sol"; @@ -57,7 +59,9 @@ library IntegrationTestHelpers { IMarketRegistry(_marketRegistry) ); EscrowVault _escrowVault = new EscrowVault(); + ProtocolPausingManager _protocolPausingManager = new ProtocolPausingManager(); + _protocolPausingManager.initialize(); //need to xfer ownership ..? _collateralManager.initialize(address(escrowBeacon), address(tellerV2)); _lenderManager.initialize(); _reputationManager.initialize(address(tellerV2)); @@ -69,7 +73,8 @@ library IntegrationTestHelpers { address(_lenderCommitmentForwarder), address(_collateralManager), address(_lenderManager), - address(_escrowVault) + address(_escrowVault), + address(_protocolPausingManager) ); return tellerV2; From fc12b92169761256f7706ae8cf2b0d9d5ba8785e Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 11:56:33 -0400 Subject: [PATCH 11/32] lot of test fail --- .../contracts/mock/TellerV2SolMock.sol | 13 +++- .../tests/TellerV2/TellerV2_Override.sol | 6 ++ .../tests/TellerV2/TellerV2_bids.sol | 23 +++++-- .../tests/TellerV2/TellerV2_initialize.sol | 25 +++++-- .../tests/TellerV2/TellerV2_pause.sol | 67 ------------------- 5 files changed, 56 insertions(+), 78 deletions(-) delete mode 100644 packages/contracts/tests/TellerV2/TellerV2_pause.sol diff --git a/packages/contracts/contracts/mock/TellerV2SolMock.sol b/packages/contracts/contracts/mock/TellerV2SolMock.sol index 457609bc8..7e5ea42ed 100644 --- a/packages/contracts/contracts/mock/TellerV2SolMock.sol +++ b/packages/contracts/contracts/mock/TellerV2SolMock.sol @@ -6,6 +6,7 @@ import "../TellerV2.sol"; import "../interfaces/ITellerV2.sol"; import "../interfaces/IProtocolFee.sol"; import "../TellerV2Context.sol"; +import "../pausing/HasProtocolPausingManager.sol"; import { Collateral } from "../interfaces/escrow/ICollateralEscrowV1.sol"; import { LoanDetails, Payment, BidState } from "../TellerV2Storage.sol"; @@ -15,7 +16,13 @@ import { ILoanRepaymentCallbacks } from "../interfaces/ILoanRepaymentCallbacks.s /* This is only used for sol test so its named specifically to avoid being used for the typescript tests. */ -contract TellerV2SolMock is ITellerV2, IProtocolFee, TellerV2Storage , ILoanRepaymentCallbacks{ +contract TellerV2SolMock is +ITellerV2, +IProtocolFee, +TellerV2Storage , +HasProtocolPausingManager, +ILoanRepaymentCallbacks +{ uint256 public amountOwedMockPrincipal; uint256 public amountOwedMockInterest; address public approvedForwarder; @@ -34,6 +41,10 @@ contract TellerV2SolMock is ITellerV2, IProtocolFee, TellerV2Storage , ILoanRepa marketRegistry = IMarketRegistry(_marketRegistry); } + function setProtocolPausingManager(address _protocolPausingManager) public { + _setProtocolPausingManager(_protocolPausingManager); + } + function getMarketRegistry() external view returns (IMarketRegistry) { return marketRegistry; } diff --git a/packages/contracts/tests/TellerV2/TellerV2_Override.sol b/packages/contracts/tests/TellerV2/TellerV2_Override.sol index 7a47bfceb..931dff781 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_Override.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_Override.sol @@ -29,6 +29,12 @@ contract TellerV2_Override is TellerV2 { lenderManager = ILenderManager(_lenderManager); } + + function setProtocolPausingManagerSuper(address _protocolPausingManager) public { + _setProtocolPausingManager(_protocolPausingManager); + } + + function setLenderManagerSuper(address _lenderManager) public initializer { lenderManager = ILenderManager(_lenderManager); } diff --git a/packages/contracts/tests/TellerV2/TellerV2_bids.sol b/packages/contracts/tests/TellerV2/TellerV2_bids.sol index 4787f7011..cf0454aed 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_bids.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_bids.sol @@ -13,6 +13,9 @@ import { CollateralManagerMock } from "../../contracts/mock/CollateralManagerMoc import { LenderManagerMock } from "../../contracts/mock/LenderManagerMock.sol"; import { MarketRegistryMock } from "../../contracts/mock/MarketRegistryMock.sol"; +import { ProtocolPausingManager } from "../../contracts/pausing/ProtocolPausingManager.sol"; + + import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "../tokens/TestERC20Token.sol"; @@ -42,6 +45,8 @@ contract TellerV2_bids_test is Testable { CollateralManagerMock collateralManagerMock; LenderManagerMock lenderManagerMock; + ProtocolPausingManager protocolPausingManager; + uint256 marketplaceId = 100; //have to copy and paste events in here to expectEmit @@ -59,6 +64,7 @@ contract TellerV2_bids_test is Testable { reputationManagerMock = new ReputationManagerMock(); collateralManagerMock = new CollateralManagerMock(); lenderManagerMock = new LenderManagerMock(); + protocolPausingManager = new ProtocolPausingManager(); borrower = new User(); lender = new User(); @@ -221,7 +227,8 @@ contract TellerV2_bids_test is Testable { } function test_submit_bid_reverts_when_protocol_IS_paused() public { - tellerV2.mock_pause(true); + tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + protocolPausingManager.pauseProtocol(); vm.expectRevert("Pausable: paused"); tellerV2.submitBid( @@ -238,7 +245,8 @@ contract TellerV2_bids_test is Testable { function test_submit_bid_Reverts_when_protocol_IS_paused__with_collateral() public { - tellerV2.mock_pause(true); + tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + protocolPausingManager.pauseProtocol(); Collateral[] memory collateral = new Collateral[](1); @@ -430,7 +438,11 @@ contract TellerV2_bids_test is Testable { tellerV2.setCollateralManagerSuper(address(collateralManagerMock)); - tellerV2.pauseProtocol(); + + + tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + protocolPausingManager.pauseProtocol(); + //tellerV2.pauseProtocol(); vm.expectRevert("Pausable: paused"); @@ -844,7 +856,10 @@ contract TellerV2_bids_test is Testable { tellerV2.setMockMsgSenderForMarket(address(lender)); tellerV2.mock_initialize(); - tellerV2.pauseProtocol(); + + tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + protocolPausingManager.pauseProtocol(); + vm.expectRevert("Pausable: paused"); vm.prank(address(lender)); diff --git a/packages/contracts/tests/TellerV2/TellerV2_initialize.sol b/packages/contracts/tests/TellerV2/TellerV2_initialize.sol index 7dbccd82f..01d12a840 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_initialize.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_initialize.sol @@ -19,6 +19,7 @@ contract TellerV2_initialize is Testable { Contract collateralManager; Contract lenderManager; Contract escrowVault; + Contract protocolPausingManager; function setUp() public { tellerV2 = new TellerV2_Override(); @@ -33,6 +34,7 @@ contract TellerV2_initialize is Testable { collateralManager = new Contract(); lenderManager = new Contract(); escrowVault = new Contract(); + protocolPausingManager = new Contract(); tellerV2.initialize( protocolFee, @@ -41,7 +43,8 @@ contract TellerV2_initialize is Testable { address(lenderCommitmentForwarder), address(collateralManager), address(lenderManager), - address(escrowVault) + address(escrowVault), + address(protocolPausingManager) ); assertEq(address(tellerV2.marketRegistry()), address(marketRegistry)); @@ -56,6 +59,7 @@ contract TellerV2_initialize is Testable { collateralManager = new Contract(); lenderManager = new Contract(); escrowVault = new Contract(); + protocolPausingManager = new Contract(); vm.expectRevert("LenderCommitmentForwarder must be a contract"); @@ -66,7 +70,8 @@ contract TellerV2_initialize is Testable { address(lenderCommitmentForwarder), address(collateralManager), address(lenderManager), - address(escrowVault) + address(escrowVault), + address(protocolPausingManager) ); } @@ -77,6 +82,7 @@ contract TellerV2_initialize is Testable { collateralManager = new Contract(); lenderManager = new Contract(); escrowVault = new Contract(); + protocolPausingManager = new Contract(); vm.expectRevert("MarketRegistry must be a contract"); @@ -87,7 +93,8 @@ contract TellerV2_initialize is Testable { address(lenderCommitmentForwarder), address(collateralManager), address(lenderManager), - address(escrowVault) + address(escrowVault), + address(protocolPausingManager) ); } @@ -98,6 +105,7 @@ contract TellerV2_initialize is Testable { collateralManager = new Contract(); lenderManager = new Contract(); escrowVault = new Contract(); + protocolPausingManager = new Contract(); vm.expectRevert("ReputationManager must be a contract"); @@ -108,7 +116,8 @@ contract TellerV2_initialize is Testable { address(lenderCommitmentForwarder), address(collateralManager), address(lenderManager), - address(escrowVault) + address(escrowVault), + address(protocolPausingManager) ); } @@ -119,6 +128,7 @@ contract TellerV2_initialize is Testable { reputationManager = new Contract(); lenderManager = new Contract(); escrowVault = new Contract(); + protocolPausingManager = new Contract(); vm.expectRevert("CollateralManager must be a contract"); @@ -129,7 +139,8 @@ contract TellerV2_initialize is Testable { address(lenderCommitmentForwarder), address(collateralManager), address(lenderManager), - address(escrowVault) + address(escrowVault), + address(protocolPausingManager) ); } @@ -140,6 +151,7 @@ contract TellerV2_initialize is Testable { reputationManager = new Contract(); collateralManager = new Contract(); escrowVault = new Contract(); + protocolPausingManager = new Contract(); vm.expectRevert("LenderManager must be a contract"); @@ -150,7 +162,8 @@ contract TellerV2_initialize is Testable { address(lenderCommitmentForwarder), address(collateralManager), address(lenderManager), - address(escrowVault) + address(escrowVault), + address(protocolPausingManager) ); } diff --git a/packages/contracts/tests/TellerV2/TellerV2_pause.sol b/packages/contracts/tests/TellerV2/TellerV2_pause.sol deleted file mode 100644 index 88f06a3e6..000000000 --- a/packages/contracts/tests/TellerV2/TellerV2_pause.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { StdStorage, stdStorage } from "forge-std/StdStorage.sol"; -import { Testable } from "../Testable.sol"; -import { TellerV2_Override } from "./TellerV2_Override.sol"; -import { Bid, BidState, Collateral, Payment, LoanDetails, Terms } from "../../contracts/TellerV2.sol"; - -import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -import { PaymentType, PaymentCycleType } from "../../contracts/libraries/V2Calculations.sol"; - -contract TellerV2_pause_test is Testable { - TellerV2_Override tellerV2; - - uint16 protocolFee = 5; - - ERC20 lendingToken; - - function setUp() public { - tellerV2 = new TellerV2_Override(); - - lendingToken = new ERC20("Wrapped Ether", "WETH"); - } - - function test_pauseProtocol_invalid_if_not_owner() public { - vm.expectRevert("Requires role: Pauser"); - - tellerV2.pauseProtocol(); - } - - function test_pauseProtocol_invalid_if_paused() public { - tellerV2.mock_initialize(); - - tellerV2.pauseProtocol(); - - vm.expectRevert(); - tellerV2.pauseProtocol(); - } - - function test_unpauseProtocol_invalid_if_unpaused() public { - tellerV2.mock_initialize(); - - vm.expectRevert(); - tellerV2.unpauseProtocol(); - } - - function test_pauseProtocol() public { - tellerV2.mock_initialize(); - - tellerV2.pauseProtocol(); - assertTrue(tellerV2.paused()); - } - - function test_unpauseProtocol() public { - tellerV2.mock_initialize(); - - tellerV2.pauseProtocol(); - assertTrue(tellerV2.paused()); - tellerV2.unpauseProtocol(); - assertFalse(tellerV2.paused()); - } -} - -contract User {} From 370a4dc19a46aca585f2028cb7b5580ffb0a7c97 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 11:58:25 -0400 Subject: [PATCH 12/32] added pauser tests --- .../tests/ProtocolPausingManager_Test.sol | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 packages/contracts/tests/ProtocolPausingManager_Test.sol diff --git a/packages/contracts/tests/ProtocolPausingManager_Test.sol b/packages/contracts/tests/ProtocolPausingManager_Test.sol new file mode 100644 index 000000000..b83376467 --- /dev/null +++ b/packages/contracts/tests/ProtocolPausingManager_Test.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "forge-std/Test.sol"; + +import "../contracts/pausing/ProtocolPausingManager.sol"; + + +contract ProtocolPausingManagerTest is Test { + ProtocolPausingManager protocolPausingManager; + address owner = address(0x1); + address pauser = address(0x2); + address nonPauser = address(0x3); + + // Events + event PausedProtocol(address indexed account); + event UnpausedProtocol(address indexed account); + event PausedLiquidations(address indexed account); + event UnpausedLiquidations(address indexed account); + event PauserAdded(address indexed account); + event PauserRemoved(address indexed account); + + function setUp() public { + vm.startPrank(owner); + protocolPausingManager = new ProtocolPausingManager(); + protocolPausingManager.initialize(); + protocolPausingManager.addPauser(pauser); + vm.stopPrank(); + } + + function test_addPauser() public { + vm.startPrank(owner); + vm.expectEmit(true, true, true, true); + emit PauserAdded(nonPauser); + protocolPausingManager.addPauser(nonPauser); + assertTrue(protocolPausingManager.isPauser(nonPauser)); + vm.stopPrank(); + } + + function test_removePauser() public { + vm.startPrank(owner); + protocolPausingManager.addPauser(nonPauser); + vm.expectEmit(true, true, true, true); + emit PauserRemoved(nonPauser); + protocolPausingManager.removePauser(nonPauser); + assertFalse(protocolPausingManager.isPauser(nonPauser)); + vm.stopPrank(); + } + + function test_pauseProtocol() public { + vm.startPrank(pauser); + vm.expectEmit(true, true, true, true); + emit PausedProtocol(pauser); + protocolPausingManager.pauseProtocol(); + assertTrue(protocolPausingManager.protocolPaused()); + vm.stopPrank(); + } + + function test_unpauseProtocol() public { + vm.startPrank(pauser); + protocolPausingManager.pauseProtocol(); + vm.expectEmit(true, true, true, true); + emit UnpausedProtocol(pauser); + protocolPausingManager.unpauseProtocol(); + assertFalse(protocolPausingManager.protocolPaused()); + vm.stopPrank(); + } + + function test_pauseLiquidations() public { + vm.startPrank(pauser); + vm.expectEmit(true, true, true, true); + emit PausedLiquidations(pauser); + protocolPausingManager.pauseLiquidations(); + assertTrue(protocolPausingManager.liquidationsPaused()); + vm.stopPrank(); + } + + function test_unpauseLiquidations() public { + vm.startPrank(pauser); + protocolPausingManager.pauseLiquidations(); + vm.expectEmit(true, true, true, true); + emit UnpausedLiquidations(pauser); + protocolPausingManager.unpauseLiquidations(); + assertFalse(protocolPausingManager.liquidationsPaused()); + vm.stopPrank(); + } + + function test_pauseProtocolFailsIfNotPauser() public { + vm.startPrank(nonPauser); + vm.expectRevert(); + protocolPausingManager.pauseProtocol(); + vm.stopPrank(); + } + + function test_unpauseProtocolFailsIfNotPauser() public { + vm.startPrank(pauser); + protocolPausingManager.pauseProtocol(); + vm.stopPrank(); + + vm.startPrank(nonPauser); + vm.expectRevert(); + protocolPausingManager.unpauseProtocol(); + vm.stopPrank(); + } + + function test_pauseLiquidationsFailsIfNotPauser() public { + vm.startPrank(nonPauser); + vm.expectRevert(); + protocolPausingManager.pauseLiquidations(); + vm.stopPrank(); + } + + function test_unpauseLiquidationsFailsIfNotPauser() public { + vm.startPrank(pauser); + protocolPausingManager.pauseLiquidations(); + vm.stopPrank(); + + vm.startPrank(nonPauser); + vm.expectRevert(); + protocolPausingManager.unpauseLiquidations(); + vm.stopPrank(); + } +} From 6286de6b3c5638fdf7e77cfc80ed9d77adcd003d Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 14:38:14 -0400 Subject: [PATCH 13/32] some tests fixed --- .../SmartCommitmentForwarder.sol | 4 +++- packages/contracts/contracts/mock/WethMock.sol | 3 +++ .../contracts/pausing/HasProtocolPausingManager.sol | 6 +++--- .../contracts/tests/TellerV2/TellerV2_Override.sol | 2 +- packages/contracts/tests/TellerV2/TellerV2_bids.sol | 12 ++++++++---- .../contracts/tests/TellerV2/TellerV2_initialize.sol | 10 +++++----- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol index ed3c06773..9e11e4b48 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol @@ -235,9 +235,11 @@ contract SmartCommitmentForwarder is returns (uint256) { + address pausingManager = IHasProtocolPausingManager( _tellerV2 ).getProtocolPausingManager(); + return MathUpgradeable.max( lastUnpausedAt, - IPausableTimestamp(_tellerV2).getLastUnpausedAt() + IPausableTimestamp(pausingManager).getLastUnpausedAt() ) ; diff --git a/packages/contracts/contracts/mock/WethMock.sol b/packages/contracts/contracts/mock/WethMock.sol index c1042ba3e..57eb817ea 100644 --- a/packages/contracts/contracts/mock/WethMock.sol +++ b/packages/contracts/contracts/mock/WethMock.sol @@ -81,4 +81,7 @@ contract WethMock { return true; } + + + } diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index ab4aa8548..09f09a38d 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -25,14 +25,14 @@ abstract contract HasProtocolPausingManager modifier whenLiquidationsNotPaused() { - require(! IProtocolPausingManager(_protocolPausingManager). liquidationsPaused() ); + require(! IProtocolPausingManager(_protocolPausingManager). liquidationsPaused(), "Liquidations paused" ); _; } //rename to when protocol not paused ? modifier whenProtocolNotPaused() { - require(! IProtocolPausingManager(_protocolPausingManager). protocolPaused() ); + require(! IProtocolPausingManager(_protocolPausingManager). protocolPaused(), "Protocol paused" ); _; } @@ -40,7 +40,7 @@ abstract contract HasProtocolPausingManager //onlyinitializing? function _setProtocolPausingManager(address protocolPausingManager) internal { - _protocolPausingManager == protocolPausingManager ; + _protocolPausingManager = protocolPausingManager ; } diff --git a/packages/contracts/tests/TellerV2/TellerV2_Override.sol b/packages/contracts/tests/TellerV2/TellerV2_Override.sol index 931dff781..714000b54 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_Override.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_Override.sol @@ -31,7 +31,7 @@ contract TellerV2_Override is TellerV2 { function setProtocolPausingManagerSuper(address _protocolPausingManager) public { - _setProtocolPausingManager(_protocolPausingManager); + super._setProtocolPausingManager(_protocolPausingManager); } diff --git a/packages/contracts/tests/TellerV2/TellerV2_bids.sol b/packages/contracts/tests/TellerV2/TellerV2_bids.sol index cf0454aed..eb6f7aa3e 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_bids.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_bids.sol @@ -160,7 +160,7 @@ contract TellerV2_bids_test is Testable { marketRegistryMock.mock_setGlobalMarketsClosed(true); - vm.expectRevert("Market is not open"); + vm.expectRevert("Mkt C"); tellerV2._submitBidSuper( address(lendingToken), // lending token @@ -180,7 +180,7 @@ contract TellerV2_bids_test is Testable { marketRegistryMock.mock_setBorrowerIsVerified(false); - vm.expectRevert("Not verified borrower"); + vm.expectRevert("Borrower NV"); tellerV2._submitBidSuper( address(lendingToken), // lending token @@ -194,6 +194,8 @@ contract TellerV2_bids_test is Testable { } function test_submit_bid_without_collateral() public { + //tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + tellerV2.submitBid( address(1), // lending token 1, // market ID @@ -208,6 +210,8 @@ contract TellerV2_bids_test is Testable { } function test_submit_bid_with_collateral() public { + // tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + tellerV2.setCollateralManagerSuper(address(collateralManagerMock)); Collateral[] memory collateral = new Collateral[](1); @@ -230,7 +234,7 @@ contract TellerV2_bids_test is Testable { tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); protocolPausingManager.pauseProtocol(); - vm.expectRevert("Pausable: paused"); + vm.expectRevert("Protocol paused"); tellerV2.submitBid( address(1), // lending token 1, // market ID @@ -250,7 +254,7 @@ contract TellerV2_bids_test is Testable { Collateral[] memory collateral = new Collateral[](1); - vm.expectRevert("Pausable: paused"); + vm.expectRevert("Protocol paused"); tellerV2.submitBid( address(1), // lending token 1, // market ID diff --git a/packages/contracts/tests/TellerV2/TellerV2_initialize.sol b/packages/contracts/tests/TellerV2/TellerV2_initialize.sol index 01d12a840..6c8df615d 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_initialize.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_initialize.sol @@ -61,7 +61,7 @@ contract TellerV2_initialize is Testable { escrowVault = new Contract(); protocolPausingManager = new Contract(); - vm.expectRevert("LenderCommitmentForwarder must be a contract"); + vm.expectRevert("LCF_ic"); tellerV2.initialize( protocolFee, @@ -84,7 +84,7 @@ contract TellerV2_initialize is Testable { escrowVault = new Contract(); protocolPausingManager = new Contract(); - vm.expectRevert("MarketRegistry must be a contract"); + vm.expectRevert("MR_ic"); tellerV2.initialize( protocolFee, @@ -107,7 +107,7 @@ contract TellerV2_initialize is Testable { escrowVault = new Contract(); protocolPausingManager = new Contract(); - vm.expectRevert("ReputationManager must be a contract"); + vm.expectRevert("RM_ic"); tellerV2.initialize( protocolFee, @@ -130,7 +130,7 @@ contract TellerV2_initialize is Testable { escrowVault = new Contract(); protocolPausingManager = new Contract(); - vm.expectRevert("CollateralManager must be a contract"); + vm.expectRevert("CM_ic"); tellerV2.initialize( protocolFee, @@ -153,7 +153,7 @@ contract TellerV2_initialize is Testable { escrowVault = new Contract(); protocolPausingManager = new Contract(); - vm.expectRevert("LenderManager must be a contract"); + vm.expectRevert("LM_ic"); tellerV2.initialize( protocolFee, From 5f1d6b3b0037b3cbb3ac14eb2754b9baa82f1889 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 14:42:49 -0400 Subject: [PATCH 14/32] fixed more tests --- packages/contracts/tests/TellerV2/TellerV2_bids.sol | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/contracts/tests/TellerV2/TellerV2_bids.sol b/packages/contracts/tests/TellerV2/TellerV2_bids.sol index eb6f7aa3e..46a072895 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_bids.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_bids.sol @@ -65,6 +65,10 @@ contract TellerV2_bids_test is Testable { collateralManagerMock = new CollateralManagerMock(); lenderManagerMock = new LenderManagerMock(); protocolPausingManager = new ProtocolPausingManager(); + protocolPausingManager.initialize(); + + tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + borrower = new User(); lender = new User(); @@ -448,7 +452,7 @@ contract TellerV2_bids_test is Testable { protocolPausingManager.pauseProtocol(); //tellerV2.pauseProtocol(); - vm.expectRevert("Pausable: paused"); + vm.expectRevert("Protocol paused"); tellerV2.lenderAcceptBid(bidId); } @@ -821,6 +825,8 @@ contract TellerV2_bids_test is Testable { uint256 bidId = 1; setMockBid(bidId); + tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + tellerV2.setLenderManagerSuper(address(lenderManagerMock)); tellerV2.mock_setBidState(bidId, BidState.ACCEPTED); @@ -837,6 +843,9 @@ contract TellerV2_bids_test is Testable { uint256 bidId = 1; setMockBid(bidId); + tellerV2.setProtocolPausingManagerSuper(address(protocolPausingManager)); + + tellerV2.setLenderManagerSuper(address(lenderManagerMock)); tellerV2.mock_setBidState(bidId, BidState.ACCEPTED); @@ -865,7 +874,7 @@ contract TellerV2_bids_test is Testable { protocolPausingManager.pauseProtocol(); - vm.expectRevert("Pausable: paused"); + vm.expectRevert("Protocol paused"); vm.prank(address(lender)); tellerV2.claimLoanNFT(bidId); } From b301ac1a1fd2902854c7a10adac5d9376a29f5ab Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 14:52:10 -0400 Subject: [PATCH 15/32] fix collateral mgr --- packages/contracts/contracts/CollateralManager.sol | 9 ++++++--- packages/contracts/tests/TellerV2/TellerV2_Test.sol | 6 +++++- packages/contracts/tests/TellerV2/TellerV2_bids.sol | 12 ++++++------ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/packages/contracts/contracts/CollateralManager.sol b/packages/contracts/contracts/CollateralManager.sol index 5d1b5a83b..c587aea29 100644 --- a/packages/contracts/contracts/CollateralManager.sol +++ b/packages/contracts/contracts/CollateralManager.sol @@ -16,7 +16,8 @@ import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradea import "./interfaces/ICollateralManager.sol"; import { Collateral, CollateralType, ICollateralEscrowV1 } from "./interfaces/escrow/ICollateralEscrowV1.sol"; import "./interfaces/ITellerV2.sol"; - +import "./interfaces/IProtocolPausingManager.sol"; +import "./interfaces/IHasProtocolPausingManager.sol"; contract CollateralManager is OwnableUpgradeable, ICollateralManager { /* Storage */ using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; @@ -78,8 +79,10 @@ contract CollateralManager is OwnableUpgradeable, ICollateralManager { _; } - modifier whenProtocolNotPaused() { - require( PausableUpgradeable(address(tellerV2)).paused() == false , "Protocol is paused"); + modifier whenProtocolNotPaused() { + address pausingManager = IHasProtocolPausingManager( address(tellerV2) ).getProtocolPausingManager(); + + require( IProtocolPausingManager(address(pausingManager)).protocolPaused() == false , "Protocol is paused"); _; } diff --git a/packages/contracts/tests/TellerV2/TellerV2_Test.sol b/packages/contracts/tests/TellerV2/TellerV2_Test.sol index 51cb794d4..4849effec 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_Test.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_Test.sol @@ -42,6 +42,7 @@ contract TellerV2_Test is Testable { WethMock wethMock; TestERC20Token daiMock; CollateralManager collateralManager; + ProtocolPausingManager protocolPausingManager; uint256 marketId1; uint256 collateralAmount = 10; @@ -81,7 +82,7 @@ contract TellerV2_Test is Testable { EscrowVault escrowVault = new EscrowVault(); escrowVault.initialize(); - ProtocolPausingManager protocolPausingManager = new ProtocolPausingManager(); + protocolPausingManager = new ProtocolPausingManager(); protocolPausingManager.initialize(); // Deploy LenderCommitmentForwarder @@ -171,6 +172,9 @@ contract TellerV2_Test is Testable { } function test_collateralEscrow() public { + + + // Submit bid as borrower uint256 bidId = submitCollateralBid(); // Accept bid as lender diff --git a/packages/contracts/tests/TellerV2/TellerV2_bids.sol b/packages/contracts/tests/TellerV2/TellerV2_bids.sol index 46a072895..ce2ff38ec 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_bids.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_bids.sol @@ -278,7 +278,7 @@ contract TellerV2_bids_test is Testable { collateralManagerMock.forceSetCommitCollateralValidation(false); - vm.expectRevert("Collateral balance could not be validated"); + vm.expectRevert("C bal NV"); tellerV2.submitBid( address(1), // lending token 1, // market ID @@ -321,7 +321,7 @@ contract TellerV2_bids_test is Testable { ActionNotAllowed.selector, bidId, "cancelBid", - "Only the bid owner can cancel!" + "Not bid owner" ) ); tellerV2.cancelBid(bidId); @@ -421,7 +421,7 @@ contract TellerV2_bids_test is Testable { ActionNotAllowed.selector, bidId, "lenderAcceptBid", - "Bid must be pending" + "Bid not pending" ) ); @@ -660,7 +660,7 @@ contract TellerV2_bids_test is Testable { ActionNotAllowed.selector, bidId, "repayLoan", - "Loan must be accepted" + "Loan not accepted" ) ); @@ -701,7 +701,7 @@ contract TellerV2_bids_test is Testable { ActionNotAllowed.selector, bidId, "repayLoan", - "Loan must be accepted" + "Loan not accepted" ) ); @@ -812,7 +812,7 @@ contract TellerV2_bids_test is Testable { ActionNotAllowed.selector, bidId, "liquidateLoan", - "Loan must be accepted" + "Loan not accepted" ) ); tellerV2.liquidateLoanFull(bidId); From 29471d4a5a30ceba4dae9fbcef1b0c4ff0721c4f Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 14:56:40 -0400 Subject: [PATCH 16/32] fixed more tests --- packages/contracts/tests/CollateralManager_Test.sol | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/contracts/tests/CollateralManager_Test.sol b/packages/contracts/tests/CollateralManager_Test.sol index 33def1d83..255e22b34 100644 --- a/packages/contracts/tests/CollateralManager_Test.sol +++ b/packages/contracts/tests/CollateralManager_Test.sol @@ -16,7 +16,7 @@ import "./tokens/TestERC1155Token.sol"; import "../contracts/mock/TellerV2SolMock.sol"; import "../contracts/CollateralManager.sol"; - +import "../contracts/pausing/ProtocolPausingManager.sol"; import "./CollateralManager_Override.sol"; contract CollateralManager_Test is Testable { @@ -73,6 +73,11 @@ contract CollateralManager_Test is Testable { lender = new User(); liquidator = new User(); + ProtocolPausingManager protocolPausingManager = new ProtocolPausingManager(); + protocolPausingManager.initialize(); + + tellerV2Mock.setProtocolPausingManager(address(protocolPausingManager)); + // uint256 borrowerBalance = 50000; // payable(address(borrower)).transfer(borrowerBalance); From 1e3224a53d65bc5836624f20e74f2911d305f4c3 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Fri, 11 Oct 2024 15:00:38 -0400 Subject: [PATCH 17/32] all tests pass --- .../LenderCommitmentGroup_Smart_Test.sol | 170 +----------------- 1 file changed, 8 insertions(+), 162 deletions(-) diff --git a/packages/contracts/tests/LenderCommitmentForwarder/extensions/SmartCommitments/LenderCommitmentGroup_Smart_Test.sol b/packages/contracts/tests/LenderCommitmentForwarder/extensions/SmartCommitments/LenderCommitmentGroup_Smart_Test.sol index ae8a6d290..d24e488f1 100644 --- a/packages/contracts/tests/LenderCommitmentForwarder/extensions/SmartCommitments/LenderCommitmentGroup_Smart_Test.sol +++ b/packages/contracts/tests/LenderCommitmentForwarder/extensions/SmartCommitments/LenderCommitmentGroup_Smart_Test.sol @@ -16,6 +16,7 @@ import { LoanDetails, Payment, BidState , Bid, Terms } from "../../../../contrac import { ILenderCommitmentGroup } from "../../../../contracts/interfaces/ILenderCommitmentGroup.sol"; import { IUniswapPricingLibrary } from "../../../../contracts/interfaces/IUniswapPricingLibrary.sol"; +import {ProtocolPausingManager} from "../../../../contracts/pausing/ProtocolPausingManager.sol"; import "lib/forge-std/src/console.sol"; @@ -75,8 +76,13 @@ contract LenderCommitmentGroup_Smart_Test is Testable { _uniswapV3Factory = new UniswapV3FactoryMock(); _uniswapV3Factory.setPoolMock(address(_uniswapV3Pool)); - vm.warp(1_000_000); - + + ProtocolPausingManager protocolPausingManager = new ProtocolPausingManager(); + protocolPausingManager.initialize(); + + _tellerV2.setProtocolPausingManager(address(protocolPausingManager)); + + principalToken = new TestERC20Token("wrappedETH", "WETH", 1e24, 18); @@ -608,166 +614,6 @@ contract LenderCommitmentGroup_Smart_Test is Testable { -/* - make sure both pos and neg branches get run, and tellerV2 is called at the end -*/ - function test_liquidateDefaultedLoanWithIncentive() public { - initialize_group_contract(); - - principalToken.transfer(address(liquidator), 1e18); - uint256 originalBalance = principalToken.balanceOf(address(liquidator)); - - uint256 amountOwed = 100; - - - uint256 bidId = 0; - - - lenderCommitmentGroupSmart.set_mockAmountOwedForBid(amountOwed); - - - - vm.warp(1000); //loanDefaultedTimeStamp ? - - lenderCommitmentGroupSmart.set_mockBidAsActiveForGroup(bidId,true); - - //set itself as mock owner for now .. used for protocol fee - _tellerV2.setMockOwner( address(lenderCommitmentGroupSmart) ); - - vm.prank(address(liquidator)); - principalToken.approve(address(lenderCommitmentGroupSmart), 1e18); - - int256 minAmountDifference = 2000; - - lenderCommitmentGroupSmart.mock_setMinimumAmountDifferenceToCloseDefaultedLoan(minAmountDifference); - - int256 tokenAmountDifference = 4000; - vm.prank(address(liquidator)); - lenderCommitmentGroupSmart.liquidateDefaultedLoanWithIncentive( - bidId, - tokenAmountDifference - ); - - uint256 updatedBalance = principalToken.balanceOf(address(liquidator)); - - int256 expectedDifference = int256(amountOwed) + minAmountDifference; - - assertEq(originalBalance - updatedBalance , uint256(expectedDifference), "unexpected tokenDifferenceFromLiquidations"); - - - //make sure lenderCloseloan is called - assertEq( _tellerV2.lenderCloseLoanWasCalled(), true, "lender close loan not called"); - } - - - //complete me - function test_liquidateDefaultedLoanWithIncentive_negative_direction() public { - - - initialize_group_contract(); - - principalToken.transfer(address(liquidator), 1e18); - uint256 originalBalance = principalToken.balanceOf(address(liquidator)); - - uint256 amountOwed = 1000; - - - uint256 bidId = 0; - - - lenderCommitmentGroupSmart.set_mockAmountOwedForBid(amountOwed); - - - //time has advanced enough to now have a 50 percent discount s - vm.warp(1000); //loanDefaultedTimeStamp ? - - lenderCommitmentGroupSmart.set_mockBidAsActiveForGroup(bidId,true); - - vm.prank(address(liquidator)); - principalToken.approve(address(lenderCommitmentGroupSmart), 1e18); - - lenderCommitmentGroupSmart.mock_setMinimumAmountDifferenceToCloseDefaultedLoan(-500); - - int256 tokenAmountDifference = -500; - vm.prank(address(liquidator)); - lenderCommitmentGroupSmart.liquidateDefaultedLoanWithIncentive( - bidId, - tokenAmountDifference - ); - - uint256 updatedBalance = principalToken.balanceOf(address(liquidator)); - - require(tokenAmountDifference < 0); //ensure this test is set up properly - - // we expect it to be amountOwned - abs(tokenAmountDifference ) but we can just test it like this - int256 expectedDifference = int256(amountOwed) + ( tokenAmountDifference); - - assertEq(originalBalance - updatedBalance , uint256(expectedDifference), "unexpected tokenDifferenceFromLiquidations"); - - - //make sure lenderCloseloan is called - assertEq( _tellerV2.lenderCloseLoanWasCalled(), true, "lender close loan not called"); - } - - -function test_liquidateDefaultedLoanWithIncentive_does_not_double_count_repaid() public { - - - initialize_group_contract(); - - principalToken.transfer(address(liquidator), 1e18); - uint256 originalBalance = principalToken.balanceOf(address(liquidator)); - - uint256 amountOwed = 1000; - - - uint256 bidId = 0; - - - lenderCommitmentGroupSmart.set_mockAmountOwedForBid(amountOwed); - - - //time has advanced enough to now have a 50 percent discount s - vm.warp(1000); //loanDefaultedTimeStamp ? - - lenderCommitmentGroupSmart.set_mockBidAsActiveForGroup(bidId,true); - - vm.prank(address(liquidator)); - principalToken.approve(address(lenderCommitmentGroupSmart), 1e18); - - - lenderCommitmentGroupSmart.set_totalPrincipalTokensRepaid(0); - - lenderCommitmentGroupSmart.mock_setMinimumAmountDifferenceToCloseDefaultedLoan(-500); - - int256 tokenAmountDifference = -500; - vm.prank(address(liquidator)); - lenderCommitmentGroupSmart.liquidateDefaultedLoanWithIncentive( - bidId, - tokenAmountDifference - ); - - //simulate the repay loan callback as would happen in a liquidation - vm.prank(address(_tellerV2)); - lenderCommitmentGroupSmart.repayLoanCallback( - bidId, - address(this), - amountOwed, - 20 - ); - - uint256 updatedBalance = principalToken.balanceOf(address(liquidator)); - - uint256 totalPrincipalTokensRepaid = lenderCommitmentGroupSmart.totalPrincipalTokensRepaid(); - - - assertEq(totalPrincipalTokensRepaid, amountOwed, "unexpected totalPrincipalTokensRepaid"); - - - //make sure lenderCloseloan is called - assertEq( _tellerV2.lenderCloseLoanWasCalled(), true, "lender close loan not called"); - } - From de1624c724c6e6275a1e57409ec411c4e9063f95 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Mon, 14 Oct 2024 15:42:32 -0400 Subject: [PATCH 18/32] add reinitializer --- packages/contracts/contracts/TellerV2.sol | 59 +++++++------ .../pausing/HasProtocolPausingManager.sol | 2 +- .../18_upgrade_teller_v2_pause_manager.ts | 85 +++++++++++++++++++ 3 files changed, 120 insertions(+), 26 deletions(-) create mode 100644 packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts diff --git a/packages/contracts/contracts/TellerV2.sol b/packages/contracts/contracts/TellerV2.sol index 29559398b..080d01ce2 100644 --- a/packages/contracts/contracts/TellerV2.sol +++ b/packages/contracts/contracts/TellerV2.sol @@ -225,32 +225,41 @@ contract TellerV2 is ); collateralManager = ICollateralManager(_collateralManager); - _setLenderManager(_lenderManager); - _setEscrowVault(_escrowVault); + + + require( + _lenderManager.isContract(), + "LM_ic" + ); + lenderManager = ILenderManager(_lenderManager); + + + + + require(_escrowVault.isContract(), "EV_ic"); + escrowVault = IEscrowVault(_escrowVault); + + + + _setProtocolPausingManager(_protocolPausingManager); } + /* function setEscrowVault(address _escrowVault) external reinitializer(9) { _setEscrowVault(_escrowVault); } */ - function _setLenderManager(address _lenderManager) - internal - onlyInitializing - { - require( - _lenderManager.isContract(), - "LM_ic" - ); - lenderManager = ILenderManager(_lenderManager); - } - function _setEscrowVault(address _escrowVault) internal onlyInitializing { - require(_escrowVault.isContract(), "EV_ic"); - escrowVault = IEscrowVault(_escrowVault); - } + function setProtocolPausingManager( + address _protocolPausingManager + ) external onlyOwner reinitializer(10) { + + _setProtocolPausingManager(_protocolPausingManager); + } + /** * @notice Function for a borrower to create a bid for a loan without Collateral. @@ -480,14 +489,14 @@ contract TellerV2 is bid.marketplaceId, sender ); - require(isVerified, "Not verified lender"); + require(isVerified, "NV"); require( !marketRegistry.isMarketClosed(bid.marketplaceId), "Market is closed" ); - require(!isLoanExpired(_bidId), "Bid has expired"); + require(!isLoanExpired(_bidId), "BE"); // Set timestamp bid.loanDetails.acceptedTimestamp = uint32(block.timestamp); @@ -566,7 +575,7 @@ contract TellerV2 is Bid storage bid = bids[_bidId]; address sender = _msgSenderForMarket(bid.marketplaceId); - require(sender == bid.lender, "only lender can claim NFT"); + require(sender == bid.lender, "NV Lender"); // set lender address to the lender manager so we know to check the owner of the NFT for the true lender bid.lender = address(USING_LENDER_MANAGER); @@ -717,13 +726,13 @@ contract TellerV2 is uint256 _bidId, address _collateralRecipient ) internal acceptedLoan(_bidId, "lenderClaimCollateral") { - require(isLoanDefaulted(_bidId), "Loan must be defaulted."); + require(isLoanDefaulted(_bidId), "ND"); Bid storage bid = bids[_bidId]; bid.state = BidState.CLOSED; address sender = _msgSenderForMarket(bid.marketplaceId); - require(sender == getLoanLender(_bidId), "only lender can close loan"); + require(sender == getLoanLender(_bidId), "NLL"); collateralManager.lenderClaimCollateralWithRecipient(_bidId, _collateralRecipient); @@ -762,7 +771,7 @@ contract TellerV2 is internal acceptedLoan(_bidId, "liquidateLoan") { - require(isLoanLiquidateable(_bidId), "Loan must be liquidateable."); + require(isLoanLiquidateable(_bidId), "NL"); Bid storage bid = bids[_bidId]; @@ -901,7 +910,7 @@ contract TellerV2 is address loanRepaymentListener = repaymentListenerForBid[_bidId]; if (loanRepaymentListener != address(0)) { - require(gasleft() >= 80000, "Insufficient gas"); //fixes the 63/64 remaining issue + require(gasleft() >= 80000, "NR gas"); //fixes the 63/64 remaining issue try ILoanRepaymentListener(loanRepaymentListener).repayLoanCallback{ gas: 80000 @@ -1207,12 +1216,12 @@ contract TellerV2 is assembly { codeSize := extcodesize(_listener) } - require(codeSize > 0, "Listener must be a contract"); + require(codeSize > 0, "Not a contract"); address sender = _msgSenderForMarket(bids[_bidId].marketplaceId); require( sender == getLoanLender(_bidId), - "Only bid lender may set repayment listener" + "Not lender" ); repaymentListenerForBid[_bidId] = _listener; diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index 09f09a38d..da6ff87db 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; -import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +//import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "../interfaces/IHasProtocolPausingManager.sol"; diff --git a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts new file mode 100644 index 000000000..736fa1e4b --- /dev/null +++ b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts @@ -0,0 +1,85 @@ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +const deployFn: DeployFunction = async (hre) => { + hre.log('----------') + hre.log('') + hre.log('TellerV2: Proposing upgrade...') + + const tellerV2 = await hre.contracts.get('TellerV2') + const trustedForwarder = await hre.contracts.get('MetaForwarder') + const v2Calculations = await hre.deployments.get('V2Calculations') + + +/* +wont work due to arg ? + + let tellerV2LegacyAddress = "0xd177f4b8e348b4c56c2ac8e03b58e41b79351a7f"; + let tellerV2LegacyImpl = await hre.ethers.getContractFactory('TellerV2Legacy', + { + libraries: { + V2Calculations: v2Calculations.address, + }, + } + ); + + await hre.upgrades.forceImport( + + tellerV2LegacyAddress, + tellerV2LegacyImpl, + + ); +*/ + + + await hre.upgrades.proposeBatchTimelock({ + title: 'TellerV2: Add Pause Manager', + description: ` +# TellerV2 + +* Adds pausing manager contract link. +`, + _steps: [ + { + proxy: tellerV2, + implFactory: await hre.ethers.getContractFactory('TellerV2', { + libraries: { + V2Calculations: v2Calculations.address, + }, + }), + + opts: { + // unsafeSkipStorageCheck: true, + unsafeAllow: [ + 'constructor', + 'state-variable-immutable', + 'external-library-linking', + ], + constructorArgs: [await trustedForwarder.getAddress()], + }, + }, + ], + }) + + + //need to reinitialize ! + + hre.log('done.') + hre.log('') + hre.log('----------') + + return true +} + +// tags and deployment +deployFn.id = 'teller-v2:pausing-upgrade' +deployFn.tags = [ + 'proposal', + 'upgrade', + 'teller-v2', + 'teller-v2:pausing-upgrade', +] +deployFn.dependencies = ['teller-v2:deploy'] +deployFn.skip = async (hre) => { + return !hre.network.live || !['goerli', 'polygon'].includes(hre.network.name) +} +export default deployFn From ad247aadbd8d65dd34918c54825bdd5bf7d310cd Mon Sep 17 00:00:00 2001 From: Admazzola Date: Mon, 14 Oct 2024 15:51:07 -0400 Subject: [PATCH 19/32] add reinit and fix tests --- .../LenderCommitmentGroup_Smart_Liquidations_Tests.sol | 7 +++++++ packages/contracts/tests/TellerV2/TellerV2_bids.sol | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/contracts/tests/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart_Liquidations_Tests.sol b/packages/contracts/tests/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart_Liquidations_Tests.sol index 7a3bd52b4..abc2cab40 100644 --- a/packages/contracts/tests/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart_Liquidations_Tests.sol +++ b/packages/contracts/tests/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart_Liquidations_Tests.sol @@ -16,6 +16,7 @@ import { LoanDetails, Payment, BidState , Bid, Terms } from "../../../../contrac import { ILenderCommitmentGroup } from "../../../../contracts/interfaces/ILenderCommitmentGroup.sol"; import { IUniswapPricingLibrary } from "../../../../contracts/interfaces/IUniswapPricingLibrary.sol"; +import {ProtocolPausingManager} from "../../../../contracts/pausing/ProtocolPausingManager.sol"; import "lib/forge-std/src/console.sol"; @@ -77,6 +78,12 @@ contract LenderCommitmentGroup_Smart_Test is Testable { + ProtocolPausingManager protocolPausingManager = new ProtocolPausingManager(); + protocolPausingManager.initialize(); + + _tellerV2.setProtocolPausingManager(address(protocolPausingManager)); + + principalToken = new TestERC20Token("wrappedETH", "WETH", 1e24, 18); diff --git a/packages/contracts/tests/TellerV2/TellerV2_bids.sol b/packages/contracts/tests/TellerV2/TellerV2_bids.sol index ce2ff38ec..fab5686b3 100644 --- a/packages/contracts/tests/TellerV2/TellerV2_bids.sol +++ b/packages/contracts/tests/TellerV2/TellerV2_bids.sol @@ -477,7 +477,7 @@ contract TellerV2_bids_test is Testable { marketRegistryMock.mock_setLenderIsVerified(false); - vm.expectRevert("Not verified lender"); + vm.expectRevert(); //NV tellerV2.lenderAcceptBid(bidId); } @@ -529,7 +529,7 @@ contract TellerV2_bids_test is Testable { vm.warp(20000); - vm.expectRevert("Bid has expired"); + vm.expectRevert() ;//BE ; tellerV2.lenderAcceptBid(bidId); } @@ -716,7 +716,7 @@ contract TellerV2_bids_test is Testable { tellerV2.mock_setBidDefaultDuration(bidId, 1000); vm.warp(2000 * 1e20); - vm.expectRevert("only lender can close loan"); + vm.expectRevert(); // NLL vm.prank(address(borrower)); tellerV2.lenderCloseLoan(bidId); } @@ -758,7 +758,7 @@ contract TellerV2_bids_test is Testable { lendingToken.approve(address(tellerV2), 1e20); - vm.expectRevert("only lender can close loan"); + vm.expectRevert(); // NLL tellerV2.lenderCloseLoan(bidId); } @@ -853,7 +853,7 @@ contract TellerV2_bids_test is Testable { tellerV2.setMockMsgSenderForMarket(address(borrower)); vm.prank(address(borrower)); - vm.expectRevert("only lender can claim NFT"); + vm.expectRevert("NV Lender"); tellerV2.claimLoanNFT(bidId); } From 6f83edfba48579536e6a31b840310042081cb543 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Mon, 14 Oct 2024 16:06:42 -0400 Subject: [PATCH 20/32] adding deploy scripts --- .../teller_v2/protocol_pausing_manager.ts | 45 +++++++++++++++++++ .../18_upgrade_teller_v2_pause_manager.ts | 16 ++++++- 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts diff --git a/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts b/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts new file mode 100644 index 000000000..2afb0c79d --- /dev/null +++ b/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts @@ -0,0 +1,45 @@ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +const deployFn: DeployFunction = async (hre) => { + + const protocolPausingManager = await hre.deployProxy( + 'ProtocolPausingManager', + { + unsafeAllow: ['constructor', 'state-variable-immutable'], + constructorArgs: [ + + ], + + //call init with no args + initArgs: [ + + ], + } + ) + + //is this correct ? + const { protocolTimelock } = await hre.getNamedAccounts() + hre.log('Transferring ownership of ProtocolPausingManager to Gnosis Safe...') + await protocolPausingManager.transferOwnership(protocolTimelock) + hre.log('done.') + + + // need to xfer ownership ! + + return true +} + +// tags and deployment +deployFn.id = 'protocol-pausing-manager:deploy' +deployFn.tags = [ + 'protocol-pausing-manager', + 'protocol-pausing-manager:deploy', +] +deployFn.dependencies = ['teller-v2:deploy' ] + +deployFn.skip = async (hre) => { + return ( + !hre.network.live || !['localhost', 'polygon'].includes(hre.network.name) + ) +} +export default deployFn diff --git a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts index 736fa1e4b..bd8a05329 100644 --- a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts +++ b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts @@ -10,6 +10,7 @@ const deployFn: DeployFunction = async (hre) => { const v2Calculations = await hre.deployments.get('V2Calculations') + const protocolPausingManager = await hre.contracts.get('ProtocolPausingManager') /* wont work due to arg ? @@ -57,6 +58,17 @@ wont work due to arg ? constructorArgs: [await trustedForwarder.getAddress()], }, }, + + { + contractAddress: await tellerV2.getAddress(), + contractImplementation: await hre.ethers.getContractFactory('TellerV2', { + libraries: { + V2Calculations: v2Calculations.address, + }, + }), + callFn: "setProtocolPausingManager", + callArgs: [await protocolPausingManager.getAddress()] + } ], }) @@ -71,14 +83,14 @@ wont work due to arg ? } // tags and deployment -deployFn.id = 'teller-v2:pausing-upgrade' +deployFn.id = 'teller-v2:pausing-manager-upgrade' deployFn.tags = [ 'proposal', 'upgrade', 'teller-v2', 'teller-v2:pausing-upgrade', ] -deployFn.dependencies = ['teller-v2:deploy'] +deployFn.dependencies = ['teller-v2:deploy','protocol-pausing-manager:deploy'] deployFn.skip = async (hre) => { return !hre.network.live || !['goerli', 'polygon'].includes(hre.network.name) } From 868725214ecc83f21204644bf66c51a67783d5f0 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Mon, 14 Oct 2024 17:28:04 -0400 Subject: [PATCH 21/32] upgrade script --- .../deploy/collateral/escrow_beacon.ts | 4 ++ .../contracts/deploy/collateral/manager.ts | 5 +++ .../lender_commitment_group_beacon.ts | 2 + .../teller_v2/protocol_pausing_manager.ts | 6 +-- .../18_upgrade_teller_v2_pause_manager.ts | 45 +++++++++++++++---- 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/packages/contracts/deploy/collateral/escrow_beacon.ts b/packages/contracts/deploy/collateral/escrow_beacon.ts index b1f8a1711..76057d206 100644 --- a/packages/contracts/deploy/collateral/escrow_beacon.ts +++ b/packages/contracts/deploy/collateral/escrow_beacon.ts @@ -9,11 +9,15 @@ const deployFn: DeployFunction = async (hre) => { } ) + //is this necessary ? const { protocolTimelock } = await hre.getNamedAccounts() hre.log('Transferring ownership of CollateralEscrowBeacon to Gnosis Safe...') await collateralEscrowBeacon.transferOwnership(protocolTimelock) hre.log('done.') + //ultimately, the owner becomes the collateral manager + //isnt this just an implementation? + return true } diff --git a/packages/contracts/deploy/collateral/manager.ts b/packages/contracts/deploy/collateral/manager.ts index 7d60021de..9b2849bdc 100644 --- a/packages/contracts/deploy/collateral/manager.ts +++ b/packages/contracts/deploy/collateral/manager.ts @@ -13,6 +13,11 @@ const deployFn: DeployFunction = async (hre) => { ], }) + + //ultimately, the owner becomes tellerV2 + + + return true } diff --git a/packages/contracts/deploy/lender_commitment_forwarder/extensions/lender_commitment_group_beacon.ts b/packages/contracts/deploy/lender_commitment_forwarder/extensions/lender_commitment_group_beacon.ts index f937e7cd9..f9a0115b0 100644 --- a/packages/contracts/deploy/lender_commitment_forwarder/extensions/lender_commitment_group_beacon.ts +++ b/packages/contracts/deploy/lender_commitment_forwarder/extensions/lender_commitment_group_beacon.ts @@ -65,6 +65,8 @@ const deployFn: DeployFunction = async (hre) => { ) + //is this necessary ? + //isnt this just an implementation? const { protocolTimelock } = await hre.getNamedAccounts() hre.log('Transferring ownership of CommitmentGroupBeacon to Gnosis Safe...') diff --git a/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts b/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts index 2afb0c79d..cbc7cc3ca 100644 --- a/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts +++ b/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts @@ -17,10 +17,10 @@ const deployFn: DeployFunction = async (hre) => { } ) - //is this correct ? - const { protocolTimelock } = await hre.getNamedAccounts() + + const { protocolOwnerSafe } = await hre.getNamedAccounts() hre.log('Transferring ownership of ProtocolPausingManager to Gnosis Safe...') - await protocolPausingManager.transferOwnership(protocolTimelock) + await protocolPausingManager.transferOwnership(protocolOwnerSafe) hre.log('done.') diff --git a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts index bd8a05329..0ad79ef89 100644 --- a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts +++ b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts @@ -10,6 +10,14 @@ const deployFn: DeployFunction = async (hre) => { const v2Calculations = await hre.deployments.get('V2Calculations') + + const smartCommitmentForwarder = await hre.contracts.get( + 'SmartCommitmentForwarder' + ) + + const collateralManager = await hre.contracts.get('CollateralManager') + const marketRegistry = await hre.contracts.get('MarketRegistry') + const protocolPausingManager = await hre.contracts.get('ProtocolPausingManager') /* wont work due to arg ? @@ -56,19 +64,38 @@ wont work due to arg ? 'external-library-linking', ], constructorArgs: [await trustedForwarder.getAddress()], + call: { + fn: 'setProtocolPausingManager', + args: [await protocolPausingManager.getAddress()], + }, + + }, }, { - contractAddress: await tellerV2.getAddress(), - contractImplementation: await hre.ethers.getContractFactory('TellerV2', { - libraries: { - V2Calculations: v2Calculations.address, - }, - }), - callFn: "setProtocolPausingManager", - callArgs: [await protocolPausingManager.getAddress()] - } + proxy: collateralManager, + implFactory: await hre.ethers.getContractFactory('CollateralManager'), + }, + + + { + proxy: smartCommitmentForwarder, + implFactory: await hre.ethers.getContractFactory( + 'SmartCommitmentForwarder' + ), + + opts: { + unsafeAllow: ['constructor', 'state-variable-immutable'], + unsafeAllowRenames: true, + // unsafeSkipStorageCheck: true, //caution ! + constructorArgs: [ + await tellerV2.getAddress(), + await marketRegistry.getAddress(), + ], + }, + }, + ], }) From 9b64aa40915faf23d9adb0e7bc9ed5231de3a590 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Mon, 14 Oct 2024 17:30:54 -0400 Subject: [PATCH 22/32] ready to deploy --- .../18_upgrade_teller_v2_pause_manager.ts | 49 ++++++++++++------- .../deployments/polygon/.migrations.json | 4 +- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts index 0ad79ef89..006c866e0 100644 --- a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts +++ b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts @@ -19,25 +19,7 @@ const deployFn: DeployFunction = async (hre) => { const marketRegistry = await hre.contracts.get('MarketRegistry') const protocolPausingManager = await hre.contracts.get('ProtocolPausingManager') -/* -wont work due to arg ? - - let tellerV2LegacyAddress = "0xd177f4b8e348b4c56c2ac8e03b58e41b79351a7f"; - let tellerV2LegacyImpl = await hre.ethers.getContractFactory('TellerV2Legacy', - { - libraries: { - V2Calculations: v2Calculations.address, - }, - } - ); - - await hre.upgrades.forceImport( - - tellerV2LegacyAddress, - tellerV2LegacyImpl, - - ); -*/ + await hre.upgrades.proposeBatchTimelock({ @@ -46,6 +28,8 @@ wont work due to arg ? # TellerV2 * Adds pausing manager contract link. +* Updates the collateral manager to be able to be paused +* Updates the SCF to be able to pause all lender pools `, _steps: [ { @@ -95,6 +79,33 @@ wont work due to arg ? ], }, }, + + + //also need the latest code for lender pools ! + /* + { + beacon: lenderCommitmentGroupBeaconProxy, + implFactory: await hre.ethers.getContractFactory('LenderCommitmentGroup_Smart', { + libraries: { + UniswapPricingLibrary: uniswapPricingLibrary.address, + }, + }), + + opts: { + unsafeSkipStorageCheck: true, + unsafeAllow: [ + 'constructor', + 'state-variable-immutable', + 'external-library-linking', + ], + constructorArgs: [ + tellerV2Address, + smartCommitmentForwarderAddress, + uniswapV3FactoryAddress, + + ], + }, + },*/ ], }) diff --git a/packages/contracts/deployments/polygon/.migrations.json b/packages/contracts/deployments/polygon/.migrations.json index f3a80bc78..17073706b 100644 --- a/packages/contracts/deployments/polygon/.migrations.json +++ b/packages/contracts/deployments/polygon/.migrations.json @@ -34,6 +34,6 @@ "lender-commitment-group-factory:deploy": 1726068336, "teller-v2:pausing-upgrade": 1727280937, "lender-commitment-group-factory:upgrade-multihop": 1727465789, - "smart-commitment-forwarder:upgrade-pausing": 1727811173, - "lender-commitment-group-beacon:upgrade": 1728403000 + "smart-commitment-forwarder:upgrade-pausing": 1727811173 + } \ No newline at end of file From 5295c45e65783a2a83f5d9c24957c7ea7f71ae11 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Mon, 14 Oct 2024 17:46:20 -0400 Subject: [PATCH 23/32] dbl check storage compat --- packages/contracts/.openzeppelin/polygon.json | 126 ++++ .../contracts/contracts/TellerV2Storage.sol | 4 +- .../pausing/HasProtocolPausingManager.sol | 20 +- .../deployments/polygon/.migrations.json | 4 +- .../polygon/ProtocolPausingManager.json | 310 +++++++++ .../polygon/UniswapPricingLibrary.json | 34 +- .../deployments/polygon/V2Calculations.json | 34 +- .../2fbfd407212128842c1766ec39678e5a.json | 602 ++++++++++++++++++ .../e99b722e6618936643bdf6ab83e66ac0.json | 434 +++++++++++++ 9 files changed, 1513 insertions(+), 55 deletions(-) create mode 100644 packages/contracts/deployments/polygon/ProtocolPausingManager.json create mode 100644 packages/contracts/deployments/polygon/solcInputs/2fbfd407212128842c1766ec39678e5a.json create mode 100644 packages/contracts/deployments/polygon/solcInputs/e99b722e6618936643bdf6ab83e66ac0.json diff --git a/packages/contracts/.openzeppelin/polygon.json b/packages/contracts/.openzeppelin/polygon.json index 679ee2679..3ab95b4cf 100644 --- a/packages/contracts/.openzeppelin/polygon.json +++ b/packages/contracts/.openzeppelin/polygon.json @@ -104,6 +104,11 @@ "address": "0x44Ce8fA66d6eDF0c5c668b818A922E772C72568B", "txHash": "0x66b45be8df47ee9a106cd542aede6cfaf3fd84ccd89296ca0a6f1ed963aa1b33", "kind": "transparent" + }, + { + "address": "0x37725D0ec727604B7B3b301B265E0688A8Eff927", + "txHash": "0xd99f013e864ceb545782b881d16b6d3f6c66ac6e4d0babbec6ee26773b77db82", + "kind": "transparent" } ], "impls": { @@ -10201,6 +10206,127 @@ }, "namespaces": {} } + }, + "c8d7b90093e71c94d09f4e272108089f270011c5e03a0bf523ee49820a9ed773": { + "address": "0x588BBC083fe6AB67C18c93BC77974e25eDd23349", + "txHash": "0x8b8d3afe2759152663bcef8735fdd3ab5a7d477aafed39a01d5b2404738c3de1", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_protocolPaused", + "offset": 0, + "slot": "101", + "type": "t_bool", + "contract": "ProtocolPausingManager", + "src": "contracts/pausing/ProtocolPausingManager.sol:36" + }, + { + "label": "_liquidationsPaused", + "offset": 1, + "slot": "101", + "type": "t_bool", + "contract": "ProtocolPausingManager", + "src": "contracts/pausing/ProtocolPausingManager.sol:37" + }, + { + "label": "pauserRoleBearer", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_bool)", + "contract": "ProtocolPausingManager", + "src": "contracts/pausing/ProtocolPausingManager.sol:43" + }, + { + "label": "lastPausedAt", + "offset": 0, + "slot": "103", + "type": "t_uint256", + "contract": "ProtocolPausingManager", + "src": "contracts/pausing/ProtocolPausingManager.sol:46" + }, + { + "label": "lastUnpausedAt", + "offset": 0, + "slot": "104", + "type": "t_uint256", + "contract": "ProtocolPausingManager", + "src": "contracts/pausing/ProtocolPausingManager.sol:47" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/contracts/contracts/TellerV2Storage.sol b/packages/contracts/contracts/TellerV2Storage.sol index 9dda615e3..ef7491a84 100644 --- a/packages/contracts/contracts/TellerV2Storage.sol +++ b/packages/contracts/contracts/TellerV2Storage.sol @@ -163,8 +163,8 @@ abstract contract TellerV2Storage_G6 is TellerV2Storage_G5 { } abstract contract TellerV2Storage_G7 is TellerV2Storage_G6 { - mapping(address => bool) public _reserved_G7_0 ;//pauserRoleBearer; - bool public _reserved_G7_1; //liquidations paused + mapping(address => bool) private __pauserRoleBearer ;//pauserRoleBearer; + bool private __liquidationsPaused; //liquidations paused } abstract contract TellerV2Storage is TellerV2Storage_G7 {} diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index da6ff87db..996babe09 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -19,9 +19,9 @@ abstract contract HasProtocolPausingManager { - bool private _reserved0;// _paused.. Deprecated , handled by pausing manager + bool private __paused;// .. Deprecated , handled by pausing manager - address private _protocolPausingManager; + address private _protocolPausingManager; // 20 bytes, gap will start at new slot modifier whenLiquidationsNotPaused() { @@ -49,21 +49,7 @@ abstract contract HasProtocolPausingManager return _protocolPausingManager; } - - /* - function isPauser(address _address) public view returns (bool){ - - return IProtocolPausingManager(_protocolPausingManager). isPauser(_address) ; - } - - function getLastUnpausedAt() - external view - returns (uint256) { - - return IPausableTimestamp(_protocolPausingManager).getLastUnpausedAt(); - - } - */ + diff --git a/packages/contracts/deployments/polygon/.migrations.json b/packages/contracts/deployments/polygon/.migrations.json index 17073706b..dd04aa678 100644 --- a/packages/contracts/deployments/polygon/.migrations.json +++ b/packages/contracts/deployments/polygon/.migrations.json @@ -34,6 +34,6 @@ "lender-commitment-group-factory:deploy": 1726068336, "teller-v2:pausing-upgrade": 1727280937, "lender-commitment-group-factory:upgrade-multihop": 1727465789, - "smart-commitment-forwarder:upgrade-pausing": 1727811173 - + "smart-commitment-forwarder:upgrade-pausing": 1727811173, + "protocol-pausing-manager:deploy": 1728941512 } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/ProtocolPausingManager.json b/packages/contracts/deployments/polygon/ProtocolPausingManager.json new file mode 100644 index 000000000..ba1963a76 --- /dev/null +++ b/packages/contracts/deployments/polygon/ProtocolPausingManager.json @@ -0,0 +1,310 @@ +{ + "address": "0x37725D0ec727604B7B3b301B265E0688A8Eff927", + "abi": [ + { + "type": "event", + "anonymous": false, + "name": "Initialized", + "inputs": [ + { + "type": "uint8", + "name": "version", + "indexed": false + } + ] + }, + { + "type": "event", + "anonymous": false, + "name": "OwnershipTransferred", + "inputs": [ + { + "type": "address", + "name": "previousOwner", + "indexed": true + }, + { + "type": "address", + "name": "newOwner", + "indexed": true + } + ] + }, + { + "type": "event", + "anonymous": false, + "name": "PausedLiquidations", + "inputs": [ + { + "type": "address", + "name": "account", + "indexed": true + } + ] + }, + { + "type": "event", + "anonymous": false, + "name": "PausedProtocol", + "inputs": [ + { + "type": "address", + "name": "account", + "indexed": true + } + ] + }, + { + "type": "event", + "anonymous": false, + "name": "PauserAdded", + "inputs": [ + { + "type": "address", + "name": "account", + "indexed": true + } + ] + }, + { + "type": "event", + "anonymous": false, + "name": "PauserRemoved", + "inputs": [ + { + "type": "address", + "name": "account", + "indexed": true + } + ] + }, + { + "type": "event", + "anonymous": false, + "name": "UnpausedLiquidations", + "inputs": [ + { + "type": "address", + "name": "account", + "indexed": true + } + ] + }, + { + "type": "event", + "anonymous": false, + "name": "UnpausedProtocol", + "inputs": [ + { + "type": "address", + "name": "account", + "indexed": true + } + ] + }, + { + "type": "function", + "name": "addPauser", + "constant": false, + "payable": false, + "inputs": [ + { + "type": "address", + "name": "_pauser" + } + ], + "outputs": [] + }, + { + "type": "function", + "name": "getLastPausedAt", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "uint256", + "name": "" + } + ] + }, + { + "type": "function", + "name": "getLastUnpausedAt", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "uint256", + "name": "" + } + ] + }, + { + "type": "function", + "name": "initialize", + "constant": false, + "payable": false, + "inputs": [], + "outputs": [] + }, + { + "type": "function", + "name": "isPauser", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [ + { + "type": "address", + "name": "_account" + } + ], + "outputs": [ + { + "type": "bool", + "name": "" + } + ] + }, + { + "type": "function", + "name": "liquidationsPaused", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "bool", + "name": "" + } + ] + }, + { + "type": "function", + "name": "owner", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "address", + "name": "" + } + ] + }, + { + "type": "function", + "name": "pauseLiquidations", + "constant": false, + "payable": false, + "inputs": [], + "outputs": [] + }, + { + "type": "function", + "name": "pauseProtocol", + "constant": false, + "payable": false, + "inputs": [], + "outputs": [] + }, + { + "type": "function", + "name": "pauserRoleBearer", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [ + { + "type": "address", + "name": "" + } + ], + "outputs": [ + { + "type": "bool", + "name": "" + } + ] + }, + { + "type": "function", + "name": "protocolPaused", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "bool", + "name": "" + } + ] + }, + { + "type": "function", + "name": "removePauser", + "constant": false, + "payable": false, + "inputs": [ + { + "type": "address", + "name": "_pauser" + } + ], + "outputs": [] + }, + { + "type": "function", + "name": "renounceOwnership", + "constant": false, + "payable": false, + "inputs": [], + "outputs": [] + }, + { + "type": "function", + "name": "transferOwnership", + "constant": false, + "payable": false, + "inputs": [ + { + "type": "address", + "name": "newOwner" + } + ], + "outputs": [] + }, + { + "type": "function", + "name": "unpauseLiquidations", + "constant": false, + "payable": false, + "inputs": [], + "outputs": [] + }, + { + "type": "function", + "name": "unpauseProtocol", + "constant": false, + "payable": false, + "inputs": [], + "outputs": [] + } + ], + "transactionHash": "0xd99f013e864ceb545782b881d16b6d3f6c66ac6e4d0babbec6ee26773b77db82", + "receipt": { + "to": null, + "from": "0xD9B023522CeCe02251d877bb0EB4f06fDe6F98E6", + "blockHash": null, + "blockNumber": null + }, + "numDeployments": 1, + "implementation": "0x588BBC083fe6AB67C18c93BC77974e25eDd23349" +} \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/UniswapPricingLibrary.json b/packages/contracts/deployments/polygon/UniswapPricingLibrary.json index cd3e192f5..a2f4d18b0 100644 --- a/packages/contracts/deployments/polygon/UniswapPricingLibrary.json +++ b/packages/contracts/deployments/polygon/UniswapPricingLibrary.json @@ -1,5 +1,5 @@ { - "address": "0x9D6fA1Fd753b9AD70De1206b74D93C3287bCD615", + "address": "0x81E108071CDcFF9ec8b9Cf443bF6c5E93a3c3313", "abi": [ { "inputs": [ @@ -94,44 +94,44 @@ "type": "function" } ], - "transactionHash": "0x0db73cf3affa379da1af3ad2e374fb06abe267c3ad3f09739db99109bc28af8a", + "transactionHash": "0x8475179e19aa0d7434ffb21f258aa84fce1a28fd22ea159b217abadb107fbf96", "receipt": { "to": null, "from": "0xD9B023522CeCe02251d877bb0EB4f06fDe6F98E6", - "contractAddress": "0x9D6fA1Fd753b9AD70De1206b74D93C3287bCD615", + "contractAddress": "0x81E108071CDcFF9ec8b9Cf443bF6c5E93a3c3313", "transactionIndex": 0, "gasUsed": "911466", - "logsBloom": "0x00000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000008000000000000000000000000000000000000000000000040000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000001000000004000000000000000000001000010000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0x49946d054e0dbead17fd63deb0f2010425c9e5b934bd9b2234bc38b1d68a93f9", - "transactionHash": "0x0db73cf3affa379da1af3ad2e374fb06abe267c3ad3f09739db99109bc28af8a", + "logsBloom": "0x00000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000008000000000000000000000000000000000000000000000040000000000800000800000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000004000000000000000000000000004000000000000000000001000000000000000000000000000000100000000000000000800000000000000000000000000000000000000000000000000000100000", + "blockHash": "0xd59aea86ab5744d601f0470960c849493be8ecc614eddbc6d8b03aec6e158a49", + "transactionHash": "0x8475179e19aa0d7434ffb21f258aa84fce1a28fd22ea159b217abadb107fbf96", "logs": [ { "transactionIndex": 0, - "blockNumber": 62305373, - "transactionHash": "0x0db73cf3affa379da1af3ad2e374fb06abe267c3ad3f09739db99109bc28af8a", + "blockNumber": 63042703, + "transactionHash": "0x8475179e19aa0d7434ffb21f258aa84fce1a28fd22ea159b217abadb107fbf96", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x000000000000000000000000d9b023522cece02251d877bb0eb4f06fde6f98e6", - "0x0000000000000000000000008e9700392f9246a6c5b32ee3ecef586f156ed683" + "0x000000000000000000000000c84c1e8dffe81c8f69f2b655557ef57d5b46beb5" ], - "data": "0x000000000000000000000000000000000000000000000000046d5cb95d0132b4000000000000000000000000000000000000000000000001c7e74174e1e0f3e20000000000000000000000000000000000000000000000790f47c20460c18e2c000000000000000000000000000000000000000000000001c379e4bb84dfc12e00000000000000000000000000000000000000000000007913b51ebdbdc2c0e0", + "data": "0x000000000000000000000000000000000000000000000000046d5cb9669ee3fe00000000000000000000000000000000000000000000000138ba0480e43877c20000000000000000000000000000000000000000000001d9439ad0d94757c556000000000000000000000000000000000000000000000001344ca7c77d9993c40000000000000000000000000000000000000000000001d948082d92adf6a954", "logIndex": 0, - "blockHash": "0x49946d054e0dbead17fd63deb0f2010425c9e5b934bd9b2234bc38b1d68a93f9" + "blockHash": "0xd59aea86ab5744d601f0470960c849493be8ecc614eddbc6d8b03aec6e158a49" } ], - "blockNumber": 62305373, + "blockNumber": 63042703, "cumulativeGasUsed": "911466", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "02094e18bee41445228a3537acfe929b", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"zeroForOne\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"twapInterval\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"token0Decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Decimals\",\"type\":\"uint256\"}],\"internalType\":\"struct IUniswapPricingLibrary.PoolRouteConfig\",\"name\":\"_poolRouteConfig\",\"type\":\"tuple\"}],\"name\":\"getUniswapPriceRatioForPool\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"priceRatio\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"zeroForOne\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"twapInterval\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"token0Decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Decimals\",\"type\":\"uint256\"}],\"internalType\":\"struct IUniswapPricingLibrary.PoolRouteConfig[]\",\"name\":\"poolRoutes\",\"type\":\"tuple[]\"}],\"name\":\"getUniswapPriceRatioForPoolRoutes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"priceRatio\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/UniswapPricingLibrary.sol\":\"UniswapPricingLibrary\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x037c334add4b033ad3493038c25be1682d78c00992e1acb0e2795caff3925271\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (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 IERC20Upgradeable {\\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 /**\\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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4e733d3164f73f461eaf9d8087a7ad1ea180bdc8ba0d3d61b0e1ae16d8e63dff\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x605434219ebbe4653f703640f06969faa5a1d78f0bfef878e5ddbb1ca369ceeb\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or 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 _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\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\",\"keccak256\":\"0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProofUpgradeable {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(\\n bytes32[] memory proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(\\n bytes32[] calldata proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value for the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n return hashes[totalHashes - 1];\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value for the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n return hashes[totalHashes - 1];\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1741ea24897cdf435d3a476e9d9280b8be58a435dacb6997d54a2aa657446e5a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary MathUpgradeable {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\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 return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\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\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\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 /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc1bd5b53319c68f84e3becd75694d941e8f4be94049903232cd8bc7c535aaa5a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSetUpgradeable {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x4807db844a856813048b5af81a764fdd25a0ae8876a3132593e8d21ddc6b607c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (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 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 /**\\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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\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 return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\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\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\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 /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\"},\"contracts/interfaces/IUniswapPricingLibrary.sol\":{\"content\":\"// SPDX-Licence-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\n\\ninterface IUniswapPricingLibrary {\\n \\n\\n struct PoolRouteConfig {\\n address pool;\\n bool zeroForOne;\\n uint32 twapInterval;\\n uint256 token0Decimals;\\n uint256 token1Decimals;\\n } \\n\\n\\n\\n function getUniswapPriceRatioForPoolRoutes(\\n PoolRouteConfig[] memory poolRoutes\\n ) external view returns (uint256 priceRatio);\\n\\n\\n function getUniswapPriceRatioForPool(\\n PoolRouteConfig memory poolRoute\\n ) external view returns (uint256 priceRatio);\\n\\n}\\n\",\"keccak256\":\"0xaac4c07c82618cc01b41d56d57b52cf134afdc2220115ccc1744adfc475c2583\"},\"contracts/interfaces/uniswap/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"./pool/IUniswapV3PoolImmutables.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolState.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolDerivedState.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolActions.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolOwnerActions.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolEvents.sol\\\";\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n IUniswapV3PoolImmutables,\\n IUniswapV3PoolState,\\n IUniswapV3PoolDerivedState,\\n IUniswapV3PoolActions,\\n IUniswapV3PoolOwnerActions,\\n IUniswapV3PoolEvents\\n{\\n\\n}\\n\",\"keccak256\":\"0xb3ab192db0227b3253579f34b108af8c91c6b54bfe805fa59f11abdcb13e87fa\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissionless pool actions\\n/// @notice Contains pool methods that can be called by anyone\\ninterface IUniswapV3PoolActions {\\n /// @notice Sets the initial price for the pool\\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\n function initialize(uint160 sqrtPriceX96) external;\\n\\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\n /// @param recipient The address for which the liquidity will be created\\n /// @param tickLower The lower tick of the position in which to add liquidity\\n /// @param tickUpper The upper tick of the position in which to add liquidity\\n /// @param amount The amount of liquidity to mint\\n /// @param data Any data that should be passed through to the callback\\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n function mint(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount,\\n bytes calldata data\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Collects tokens owed to a position\\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\n /// @param recipient The address which should receive the fees collected\\n /// @param tickLower The lower tick of the position for which to collect fees\\n /// @param tickUpper The upper tick of the position for which to collect fees\\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\n /// @return amount0 The amount of fees collected in token0\\n /// @return amount1 The amount of fees collected in token1\\n function collect(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n\\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\n /// @dev Fees must be collected separately via a call to #collect\\n /// @param tickLower The lower tick of the position for which to burn liquidity\\n /// @param tickUpper The upper tick of the position for which to burn liquidity\\n /// @param amount How much liquidity to burn\\n /// @return amount0 The amount of token0 sent to the recipient\\n /// @return amount1 The amount of token1 sent to the recipient\\n function burn(int24 tickLower, int24 tickUpper, uint128 amount)\\n external\\n returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Swap token0 for token1, or token1 for token0\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\n /// @param recipient The address to receive the output of the swap\\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\n /// @param data Any data to be passed through to the callback\\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n\\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\n /// @param recipient The address which will receive the token0 and token1 amounts\\n /// @param amount0 The amount of token0 to send\\n /// @param amount1 The amount of token1 to send\\n /// @param data Any data to be passed through to the callback\\n function flash(\\n address recipient,\\n uint256 amount0,\\n uint256 amount1,\\n bytes calldata data\\n ) external;\\n\\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\n /// the input observationCardinalityNext.\\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\n function increaseObservationCardinalityNext(\\n uint16 observationCardinalityNext\\n ) external;\\n}\\n\",\"keccak256\":\"0x0d71eeba27d612d047b327e34231360e4e0014d0241e791e5ad62fb40a1a73b3\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolDerivedState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that is not stored\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\n/// blockchain. The functions here may have variable gas costs.\\ninterface IUniswapV3PoolDerivedState {\\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\n /// you must call it with secondsAgos = [3600, 0].\\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\n /// timestamp\\n function observe(uint32[] calldata secondsAgos)\\n external\\n view\\n returns (\\n int56[] memory tickCumulatives,\\n uint160[] memory secondsPerLiquidityCumulativeX128s\\n );\\n\\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\n /// snapshot is taken and the second snapshot is taken.\\n /// @param tickLower The lower tick of the range\\n /// @param tickUpper The upper tick of the range\\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\n /// @return secondsInside The snapshot of seconds per liquidity for the range\\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (\\n int56 tickCumulativeInside,\\n uint160 secondsPerLiquidityInsideX128,\\n uint32 secondsInside\\n );\\n}\\n\",\"keccak256\":\"0x75a1cde36f8d8e785df6b61c2b87c9a25f1a7bf05567bd490f021113286c7966\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Events emitted by a pool\\n/// @notice Contains all events emitted by the pool\\ninterface IUniswapV3PoolEvents {\\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\n event Initialize(uint160 sqrtPriceX96, int24 tick);\\n\\n /// @notice Emitted when liquidity is minted for a given position\\n /// @param sender The address that minted the liquidity\\n /// @param owner The owner of the position and recipient of any minted liquidity\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity minted to the position range\\n /// @param amount0 How much token0 was required for the minted liquidity\\n /// @param amount1 How much token1 was required for the minted liquidity\\n event Mint(\\n address sender,\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted when fees are collected by the owner of a position\\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\n /// @param owner The owner of the position for which fees are collected\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount0 The amount of token0 fees collected\\n /// @param amount1 The amount of token1 fees collected\\n event Collect(\\n address indexed owner,\\n address recipient,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount0,\\n uint128 amount1\\n );\\n\\n /// @notice Emitted when a position's liquidity is removed\\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\n /// @param owner The owner of the position for which liquidity is removed\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity to remove\\n /// @param amount0 The amount of token0 withdrawn\\n /// @param amount1 The amount of token1 withdrawn\\n event Burn(\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted by the pool for any swaps between token0 and token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the output of the swap\\n /// @param amount0 The delta of the token0 balance of the pool\\n /// @param amount1 The delta of the token1 balance of the pool\\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\n /// @param liquidity The liquidity of the pool after the swap\\n /// @param tick The log base 1.0001 of price of the pool after the swap\\n event Swap(\\n address indexed sender,\\n address indexed recipient,\\n int256 amount0,\\n int256 amount1,\\n uint160 sqrtPriceX96,\\n uint128 liquidity,\\n int24 tick\\n );\\n\\n /// @notice Emitted by the pool for any flashes of token0/token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the tokens from flash\\n /// @param amount0 The amount of token0 that was flashed\\n /// @param amount1 The amount of token1 that was flashed\\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\n event Flash(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1,\\n uint256 paid0,\\n uint256 paid1\\n );\\n\\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\n /// just before a mint/swap/burn.\\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\n event IncreaseObservationCardinalityNext(\\n uint16 observationCardinalityNextOld,\\n uint16 observationCardinalityNextNew\\n );\\n\\n /// @notice Emitted when the protocol fee is changed by the pool\\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\\n /// @param feeProtocol0New The updated value of the token0 protocol fee\\n /// @param feeProtocol1New The updated value of the token1 protocol fee\\n event SetFeeProtocol(\\n uint8 feeProtocol0Old,\\n uint8 feeProtocol1Old,\\n uint8 feeProtocol0New,\\n uint8 feeProtocol1New\\n );\\n\\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\n /// @param sender The address that collects the protocol fees\\n /// @param recipient The address that receives the collected protocol fees\\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\\n event CollectProtocol(\\n address indexed sender,\\n address indexed recipient,\\n uint128 amount0,\\n uint128 amount1\\n );\\n}\\n\",\"keccak256\":\"0x7209000762e515eceabd42bc2660497d91dfa33099f99d8fc3c55dd1b9578744\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolImmutables.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that never changes\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\ninterface IUniswapV3PoolImmutables {\\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\n /// @return The contract address\\n function factory() external view returns (address);\\n\\n /// @notice The first of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token0() external view returns (address);\\n\\n /// @notice The second of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token1() external view returns (address);\\n\\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\n /// @return The fee\\n function fee() external view returns (uint24);\\n\\n /// @notice The pool tick spacing\\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\n /// This value is an int24 to avoid casting even though it is always positive.\\n /// @return The tick spacing\\n function tickSpacing() external view returns (int24);\\n\\n /// @notice The maximum amount of position liquidity that can use any tick in the range\\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\n /// @return The max amount of liquidity per tick\\n function maxLiquidityPerTick() external view returns (uint128);\\n}\\n\",\"keccak256\":\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolOwnerActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissioned pool actions\\n/// @notice Contains pool methods that may only be called by the factory owner\\ninterface IUniswapV3PoolOwnerActions {\\n /// @notice Set the denominator of the protocol's % share of the fees\\n /// @param feeProtocol0 new protocol fee for token0 of the pool\\n /// @param feeProtocol1 new protocol fee for token1 of the pool\\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\n\\n /// @notice Collect the protocol fee accrued to the pool\\n /// @param recipient The address to which collected protocol fees should be sent\\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\n /// @return amount0 The protocol fee collected in token0\\n /// @return amount1 The protocol fee collected in token1\\n function collectProtocol(\\n address recipient,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n /// when accessed externally.\\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n /// boundary.\\n /// observationIndex The index of the last oracle observation that was written,\\n /// observationCardinality The current maximum number of observations stored in the pool,\\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n /// feeProtocol The protocol fee for both tokens of the pool.\\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n /// unlocked Whether the pool is currently locked to reentrancy\\n function slot0()\\n external\\n view\\n returns (\\n uint160 sqrtPriceX96,\\n int24 tick,\\n uint16 observationIndex,\\n uint16 observationCardinality,\\n uint16 observationCardinalityNext,\\n uint8 feeProtocol,\\n bool unlocked\\n );\\n\\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n /// @notice The amounts of token0 and token1 that are owed to the protocol\\n /// @dev Protocol fees will never exceed uint128 max in either token\\n function protocolFees()\\n external\\n view\\n returns (uint128 token0, uint128 token1);\\n\\n /// @notice The currently in range liquidity available to the pool\\n /// @dev This value has no relationship to the total liquidity across all ticks\\n function liquidity() external view returns (uint128);\\n\\n /// @notice Look up information about a specific tick in the pool\\n /// @param tick The tick to look up\\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n /// tick upper,\\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n /// a specific position.\\n function ticks(int24 tick)\\n external\\n view\\n returns (\\n uint128 liquidityGross,\\n int128 liquidityNet,\\n uint256 feeGrowthOutside0X128,\\n uint256 feeGrowthOutside1X128,\\n int56 tickCumulativeOutside,\\n uint160 secondsPerLiquidityOutsideX128,\\n uint32 secondsOutside,\\n bool initialized\\n );\\n\\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n /// @notice Returns the information about a position by the position's key\\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n /// @return _liquidity The amount of liquidity in the position,\\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n function positions(bytes32 key)\\n external\\n view\\n returns (\\n uint128 _liquidity,\\n uint256 feeGrowthInside0LastX128,\\n uint256 feeGrowthInside1LastX128,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n );\\n\\n /// @notice Returns data about a specific observation index\\n /// @param index The element of the observations array to fetch\\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n /// ago, rather than at a specific index in the array.\\n /// @return blockTimestamp The timestamp of the observation,\\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n /// Returns initialized whether the observation has been initialized and the values are safe to use\\n function observations(uint256 index)\\n external\\n view\\n returns (\\n uint32 blockTimestamp,\\n int56 tickCumulative,\\n uint160 secondsPerLiquidityCumulativeX128,\\n bool initialized\\n );\\n}\\n\",\"keccak256\":\"0x29867ae7524b2ae6581b95abf0c1dd1f697f0494d4c333058a00cdb215f83a43\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/UniswapPricingLibrary.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\n// Contracts\\n//import \\\"../TellerV2MarketForwarder_G2.sol\\\";\\n\\n// Interfaces\\n//import \\\"../interfaces/ICollateralManager.sol\\\"; \\n\\nimport {IUniswapPricingLibrary} from \\\"../interfaces/IUniswapPricingLibrary.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n//import { Collateral, CollateralType } from \\\"../interfaces/escrow/ICollateralEscrowV1.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\\\";\\n\\n// Libraries\\nimport { MathUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\\\";\\n\\nimport \\\"../interfaces/uniswap/IUniswapV3Pool.sol\\\";\\n//import \\\"../interfaces/uniswap/IUniswapV3Factory.sol\\\";\\n\\nimport \\\"../libraries/uniswap/TickMath.sol\\\";\\nimport \\\"../libraries/uniswap/FixedPoint96.sol\\\";\\nimport \\\"../libraries/uniswap/FullMath.sol\\\";\\n\\n//import \\\"../libraries/NumbersLib.sol\\\";\\n \\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\n\\n\\n/*\\n\\nOnly do decimal expansion if it is an ERC20 not anything else !! \\n\\n*/\\n\\nlibrary UniswapPricingLibrary \\n{\\n // using NumbersLib for uint256;\\n \\n uint256 constant STANDARD_EXPANSION_FACTOR = 1e18;\\n\\n function getUniswapPriceRatioForPoolRoutes(\\n IUniswapPricingLibrary.PoolRouteConfig[] memory poolRoutes\\n ) public view returns (uint256 priceRatio) {\\n require(poolRoutes.length <= 2, \\\"invalid pool routes length\\\");\\n\\n if (poolRoutes.length == 2) {\\n uint256 pool0PriceRatio = getUniswapPriceRatioForPool(\\n poolRoutes[0]\\n );\\n\\n uint256 pool1PriceRatio = getUniswapPriceRatioForPool(\\n poolRoutes[1]\\n );\\n\\n return\\n FullMath.mulDiv(\\n pool0PriceRatio,\\n pool1PriceRatio,\\n STANDARD_EXPANSION_FACTOR\\n );\\n } else if (poolRoutes.length == 1) {\\n return getUniswapPriceRatioForPool(poolRoutes[0]);\\n }\\n\\n //else return 0\\n }\\n\\n /*\\n The resultant product is expanded by STANDARD_EXPANSION_FACTOR one time \\n */\\n function getUniswapPriceRatioForPool(\\n IUniswapPricingLibrary.PoolRouteConfig memory _poolRouteConfig\\n ) public view returns (uint256 priceRatio) {\\n uint160 sqrtPriceX96 = getSqrtTwapX96(\\n _poolRouteConfig.pool,\\n _poolRouteConfig.twapInterval\\n );\\n\\n //This is the token 1 per token 0 price\\n uint256 sqrtPrice = FullMath.mulDiv(\\n sqrtPriceX96,\\n STANDARD_EXPANSION_FACTOR,\\n 2**96\\n );\\n\\n uint256 sqrtPriceInverse = (STANDARD_EXPANSION_FACTOR *\\n STANDARD_EXPANSION_FACTOR) / sqrtPrice;\\n\\n uint256 price = _poolRouteConfig.zeroForOne\\n ? sqrtPrice * sqrtPrice\\n : sqrtPriceInverse * sqrtPriceInverse;\\n\\n return price / STANDARD_EXPANSION_FACTOR;\\n }\\n\\n\\n\\n function getSqrtTwapX96(address uniswapV3Pool, uint32 twapInterval)\\n internal\\n view\\n returns (uint160 sqrtPriceX96)\\n {\\n if (twapInterval == 0) {\\n // return the current price if twapInterval == 0\\n (sqrtPriceX96, , , , , , ) = IUniswapV3Pool(uniswapV3Pool).slot0();\\n } else {\\n uint32[] memory secondsAgos = new uint32[](2);\\n secondsAgos[0] = twapInterval + 1; // from (before)\\n secondsAgos[1] = 1; // one block prior\\n\\n (int56[] memory tickCumulatives, ) = IUniswapV3Pool(uniswapV3Pool)\\n .observe(secondsAgos);\\n\\n // tick(imprecise as it's an integer) to price\\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(\\n int24(\\n (tickCumulatives[1] - tickCumulatives[0]) /\\n int32(twapInterval)\\n )\\n );\\n }\\n }\\n\\n function getPriceX96FromSqrtPriceX96(uint160 sqrtPriceX96)\\n internal\\n pure\\n returns (uint256 priceX96)\\n { \\n\\n \\n return FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96);\\n }\\n\\n}\",\"keccak256\":\"0x9742e975adf6260e3f0ad27bf7749f348d070d04054d876cb15870622ab4a42e\",\"license\":\"MIT\"},\"contracts/libraries/uniswap/FixedPoint96.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.4.0;\\n\\n/// @title FixedPoint96\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\n/// @dev Used in SqrtPriceMath.sol\\nlibrary FixedPoint96 {\\n uint8 internal constant RESOLUTION = 96;\\n uint256 internal constant Q96 = 0x1000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/uniswap/FullMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n /// @notice Calculates floor(a\\u00d7b\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n /// @param a The multiplicand\\n /// @param b The multiplier\\n /// @param denominator The divisor\\n /// @return result The 256-bit result\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\n function mulDiv(uint256 a, uint256 b, uint256 denominator)\\n internal\\n pure\\n returns (uint256 result)\\n {\\n // 512-bit multiply [prod1 prod0] = a * b\\n // Compute the product mod 2**256 and mod 2**256 - 1\\n // then use the Chinese Remainder Theorem to reconstruct\\n // 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(a, b, not(0))\\n prod0 := mul(a, b)\\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 require(denominator > 0);\\n assembly {\\n result := div(prod0, denominator)\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2**256.\\n // Also prevents denominator == 0\\n require(denominator > prod1);\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0]\\n // Compute remainder using mulmod\\n uint256 remainder;\\n assembly {\\n remainder := mulmod(a, b, denominator)\\n }\\n // Subtract 256 bit number from 512 bit number\\n assembly {\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator\\n // Compute largest power of two divisor of denominator.\\n // Always >= 1.\\n // uint256 twos = -denominator & denominator;\\n uint256 twos = (~denominator + 1) & denominator;\\n // Divide denominator by power of two\\n assembly {\\n denominator := div(denominator, twos)\\n }\\n\\n // Divide [prod1 prod0] by the factors of two\\n assembly {\\n prod0 := div(prod0, twos)\\n }\\n // Shift in bits from prod1 into prod0. For this we need\\n // to flip `twos` such that it is 2**256 / twos.\\n // If twos is zero, then it becomes one\\n assembly {\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2**256\\n // Now that denominator is an odd number, it has an inverse\\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n // Compute the inverse by starting with a seed that is correct\\n // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n uint256 inv = (3 * denominator) ^ 2;\\n // Now use Newton-Raphson iteration to improve the precision.\\n // Thanks to Hensel's lifting lemma, this also works in modular\\n // arithmetic, doubling the correct bits in each step.\\n inv *= 2 - denominator * inv; // inverse mod 2**8\\n inv *= 2 - denominator * inv; // inverse mod 2**16\\n inv *= 2 - denominator * inv; // inverse mod 2**32\\n inv *= 2 - denominator * inv; // inverse mod 2**64\\n inv *= 2 - denominator * inv; // inverse mod 2**128\\n inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n // Because the division is now exact we can divide by multiplying\\n // with the modular inverse of denominator. This will give us the\\n // correct result modulo 2**256. Since the precoditions guarantee\\n // that the outcome is less than 2**256, this is the final result.\\n // We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inv;\\n return result;\\n }\\n\\n /// @notice Calculates ceil(a\\u00d7b\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n /// @param a The multiplicand\\n /// @param b The multiplier\\n /// @param denominator The divisor\\n /// @return result The 256-bit result\\n function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator)\\n internal\\n pure\\n returns (uint256 result)\\n {\\n result = mulDiv(a, b, denominator);\\n if (mulmod(a, b, denominator) > 0) {\\n require(result < type(uint256).max);\\n result++;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfb50b2e1fa576851562dd6cebc786506f40f69097955e7c9e3d501899b90c8cd\",\"license\":\"MIT\"},\"contracts/libraries/uniswap/TickMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity ^0.8.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n int24 internal constant MIN_TICK = -887272;\\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n uint160 internal constant MAX_SQRT_RATIO =\\n 1461446703485210103287273052203988822378723970342;\\n\\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n /// @dev Throws if |tick| > max tick\\n /// @param tick The input tick for the above formula\\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n /// at the given tick\\n function getSqrtRatioAtTick(int24 tick)\\n internal\\n pure\\n returns (uint160 sqrtPriceX96)\\n {\\n uint256 absTick = tick < 0\\n ? uint256(-int256(tick))\\n : uint256(int256(tick));\\n require(absTick <= uint256(uint24(MAX_TICK)), \\\"T\\\");\\n\\n uint256 ratio = absTick & 0x1 != 0\\n ? 0xfffcb933bd6fad37aa2d162d1a594001\\n : 0x100000000000000000000000000000000;\\n if (absTick & 0x2 != 0)\\n ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n if (absTick & 0x4 != 0)\\n ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n if (absTick & 0x8 != 0)\\n ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n if (absTick & 0x10 != 0)\\n ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n if (absTick & 0x20 != 0)\\n ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n if (absTick & 0x40 != 0)\\n ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n if (absTick & 0x80 != 0)\\n ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n if (absTick & 0x100 != 0)\\n ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n if (absTick & 0x200 != 0)\\n ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n if (absTick & 0x400 != 0)\\n ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n if (absTick & 0x800 != 0)\\n ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n if (absTick & 0x1000 != 0)\\n ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n if (absTick & 0x2000 != 0)\\n ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n if (absTick & 0x4000 != 0)\\n ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n if (absTick & 0x8000 != 0)\\n ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n if (absTick & 0x10000 != 0)\\n ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n if (absTick & 0x20000 != 0)\\n ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n if (absTick & 0x40000 != 0)\\n ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n if (absTick & 0x80000 != 0)\\n ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n sqrtPriceX96 = uint160(\\n (ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)\\n );\\n }\\n\\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n /// ever return.\\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n function getTickAtSqrtRatio(uint160 sqrtPriceX96)\\n internal\\n pure\\n returns (int24 tick)\\n {\\n // second inequality must be < because the price can never reach the price at the max tick\\n require(\\n sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO,\\n \\\"R\\\"\\n );\\n uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n uint256 r = ratio;\\n uint256 msb = 0;\\n\\n assembly {\\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(5, gt(r, 0xFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(4, gt(r, 0xFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(3, gt(r, 0xFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(2, gt(r, 0xF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(1, gt(r, 0x3))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := gt(r, 0x1)\\n msb := or(msb, f)\\n }\\n\\n if (msb >= 128) r = ratio >> (msb - 127);\\n else r = ratio << (127 - msb);\\n\\n int256 log_2 = (int256(msb) - 128) << 64;\\n\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(63, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(62, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(61, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(60, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(59, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(58, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(57, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(56, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(55, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(54, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(53, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(52, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(51, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(50, f))\\n }\\n\\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n int24 tickLow = int24(\\n (log_sqrt10001 - 3402992956809132418596140100660247210) >> 128\\n );\\n int24 tickHi = int24(\\n (log_sqrt10001 + 291339464771989622907027621153398088495) >> 128\\n );\\n\\n tick = tickLow == tickHi\\n ? tickLow\\n : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96\\n ? tickHi\\n : tickLow;\\n }\\n}\\n\",\"keccak256\":\"0xf98bbfc8977090f026ee4b8389bb1e2e903eb0575fceea10edb373f33d51d013\",\"license\":\"GPL-2.0-or-later\"}},\"version\":1}", - "bytecode": "0x610f8761003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80631217931b14610045578063caf0f0331461006a575b600080fd5b610058610053366004610a8e565b61007d565b60405190815260200160405180910390f35b610058610078366004610ace565b61011b565b60008061009283600001518460400151610205565b905060006100b6826001600160a01b0316670de0b6b3a7640000600160601b6103fa565b90506000816100cd670de0b6b3a764000080610b83565b6100d79190610bb8565b9050600085602001516100f3576100ee8280610b83565b6100fd565b6100fd8380610b83565b9050610111670de0b6b3a764000082610bb8565b9695505050505050565b60006002825111156101745760405162461bcd60e51b815260206004820152601a60248201527f696e76616c696420706f6f6c20726f75746573206c656e67746800000000000060448201526064015b60405180910390fd5b8151600214156101da5760006101a38360008151811061019657610196610bcc565b602002602001015161007d565b905060006101bd8460018151811061019657610196610bcc565b90506101d28282670de0b6b3a76400006103fa565b949350505050565b815160011415610200576101fa8260008151811061019657610196610bcc565b92915050565b919050565b600063ffffffff821661029257826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561024b57600080fd5b505afa15801561025f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102839190610bf4565b509495506101fa945050505050565b6040805160028082526060820183526000926020830190803683370190505090506102be836001610c93565b816000815181106102d1576102d1610bcc565b602002602001019063ffffffff16908163ffffffff168152505060018160018151811061030057610300610bcc565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0386169063883bdbfd90610344908590600401610cbb565b60006040518083038186803b15801561035c57600080fd5b505afa158015610370573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103989190810190610d74565b5090506103f18460030b826000815181106103b5576103b5610bcc565b6020026020010151836001815181106103d0576103d0610bcc565b60200260200101516103e29190610e40565b6103ec9190610e90565b610576565b95945050505050565b600080806000198587098587029250828110838203039150508060001415610434576000841161042957600080fd5b50829004905061056f565b80841161044057600080fd5b60008486880980840393811190920391905060008561046181196001610ece565b169586900495938490049360008190030460010190506104818184610b83565b909317926000610492876003610b83565b60021890506104a18188610b83565b6104ac906002610ee6565b6104b69082610b83565b90506104c28188610b83565b6104cd906002610ee6565b6104d79082610b83565b90506104e38188610b83565b6104ee906002610ee6565b6104f89082610b83565b90506105048188610b83565b61050f906002610ee6565b6105199082610b83565b90506105258188610b83565b610530906002610ee6565b61053a9082610b83565b90506105468188610b83565b610551906002610ee6565b61055b9082610b83565b90506105678186610b83565b955050505050505b9392505050565b60008060008360020b1261058d578260020b61059a565b8260020b61059a90610efd565b90506105a9620d89e719610f1a565b62ffffff168111156105e15760405162461bcd60e51b81526020600482015260016024820152601560fa1b604482015260640161016b565b6000600182166105f557600160801b610607565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610646576080610641826ffff97272373d413259a46990580e213a610b83565b901c90505b600482161561067057608061066b826ffff2e50f5f656932ef12357cf3c7fdcc610b83565b901c90505b600882161561069a576080610695826fffe5caca7e10e4e61c3624eaa0941cd0610b83565b901c90505b60108216156106c45760806106bf826fffcb9843d60f6159c9db58835c926644610b83565b901c90505b60208216156106ee5760806106e9826fff973b41fa98c081472e6896dfb254c0610b83565b901c90505b6040821615610718576080610713826fff2ea16466c96a3843ec78b326b52861610b83565b901c90505b608082161561074257608061073d826ffe5dee046a99a2a811c461f1969c3053610b83565b901c90505b61010082161561076d576080610768826ffcbe86c7900a88aedcffc83b479aa3a4610b83565b901c90505b610200821615610798576080610793826ff987a7253ac413176f2b074cf7815e54610b83565b901c90505b6104008216156107c35760806107be826ff3392b0822b70005940c7a398e4b70f3610b83565b901c90505b6108008216156107ee5760806107e9826fe7159475a2c29b7443b29c7fa6e889d9610b83565b901c90505b611000821615610819576080610814826fd097f3bdfd2022b8845ad8f792aa5825610b83565b901c90505b61200082161561084457608061083f826fa9f746462d870fdf8a65dc1f90e061e5610b83565b901c90505b61400082161561086f57608061086a826f70d869a156d2a1b890bb3df62baf32f7610b83565b901c90505b61800082161561089a576080610895826f31be135f97d08fd981231505542fcfa6610b83565b901c90505b620100008216156108c65760806108c1826f09aa508b5b7a84e1c677de54f3e99bc9610b83565b901c90505b620200008216156108f15760806108ec826e5d6af8dedb81196699c329225ee604610b83565b901c90505b6204000082161561091b576080610916826d2216e584f5fa1ea926041bedfe98610b83565b901c90505b6208000082161561094357608061093e826b048a170391f7dc42444e8fa2610b83565b901c90505b60008460020b131561095e5761095b81600019610bb8565b90505b61096d64010000000082610f3d565b1561097957600161097c565b60005b6101d29060ff16602083901c610ece565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109cc576109cc61098d565b604052919050565b6001600160a01b03811681146109e957600080fd5b50565b80151581146109e957600080fd5b600060a08284031215610a0c57600080fd5b60405160a0810181811067ffffffffffffffff82111715610a2f57610a2f61098d565b6040529050808235610a40816109d4565b81526020830135610a50816109ec565b6020820152604083013563ffffffff81168114610a6c57600080fd5b8060408301525060608301356060820152608083013560808201525092915050565b600060a08284031215610aa057600080fd5b61056f83836109fa565b600067ffffffffffffffff821115610ac457610ac461098d565b5060051b60200190565b60006020808385031215610ae157600080fd5b823567ffffffffffffffff811115610af857600080fd5b8301601f81018513610b0957600080fd5b8035610b1c610b1782610aaa565b6109a3565b81815260a09182028301840191848201919088841115610b3b57600080fd5b938501935b83851015610b6157610b5289866109fa565b83529384019391850191610b40565b50979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610b9d57610b9d610b6d565b500290565b634e487b7160e01b600052601260045260246000fd5b600082610bc757610bc7610ba2565b500490565b634e487b7160e01b600052603260045260246000fd5b805161ffff8116811461020057600080fd5b600080600080600080600060e0888a031215610c0f57600080fd5b8751610c1a816109d4565b8097505060208801518060020b8114610c3257600080fd5b9550610c4060408901610be2565b9450610c4e60608901610be2565b9350610c5c60808901610be2565b925060a088015160ff81168114610c7257600080fd5b60c0890151909250610c83816109ec565b8091505092959891949750929550565b600063ffffffff808316818516808303821115610cb257610cb2610b6d565b01949350505050565b6020808252825182820181905260009190848201906040850190845b81811015610cf957835163ffffffff1683529284019291840191600101610cd7565b50909695505050505050565b600082601f830112610d1657600080fd5b81516020610d26610b1783610aaa565b82815260059290921b84018101918181019086841115610d4557600080fd5b8286015b84811015610d69578051610d5c816109d4565b8352918301918301610d49565b509695505050505050565b60008060408385031215610d8757600080fd5b825167ffffffffffffffff80821115610d9f57600080fd5b818501915085601f830112610db357600080fd5b81516020610dc3610b1783610aaa565b82815260059290921b84018101918181019089841115610de257600080fd5b948201945b83861015610e105785518060060b8114610e015760008081fd5b82529482019490820190610de7565b91880151919650909350505080821115610e2957600080fd5b50610e3685828601610d05565b9150509250929050565b60008160060b8360060b6000811281667fffffffffffff1901831281151615610e6b57610e6b610b6d565b81667fffffffffffff018313811615610e8657610e86610b6d565b5090039392505050565b60008160060b8360060b80610ea757610ea7610ba2565b667fffffffffffff19821460001982141615610ec557610ec5610b6d565b90059392505050565b60008219821115610ee157610ee1610b6d565b500190565b600082821015610ef857610ef8610b6d565b500390565b6000600160ff1b821415610f1357610f13610b6d565b5060000390565b60008160020b627fffff19811415610f3457610f34610b6d565b60000392915050565b600082610f4c57610f4c610ba2565b50069056fea2646970667358221220a3510e361726cb15bfcf40c4cedef84f1b2d4fcb803fb69d338beac2206b8a0c64736f6c63430008090033", - "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80631217931b14610045578063caf0f0331461006a575b600080fd5b610058610053366004610a8e565b61007d565b60405190815260200160405180910390f35b610058610078366004610ace565b61011b565b60008061009283600001518460400151610205565b905060006100b6826001600160a01b0316670de0b6b3a7640000600160601b6103fa565b90506000816100cd670de0b6b3a764000080610b83565b6100d79190610bb8565b9050600085602001516100f3576100ee8280610b83565b6100fd565b6100fd8380610b83565b9050610111670de0b6b3a764000082610bb8565b9695505050505050565b60006002825111156101745760405162461bcd60e51b815260206004820152601a60248201527f696e76616c696420706f6f6c20726f75746573206c656e67746800000000000060448201526064015b60405180910390fd5b8151600214156101da5760006101a38360008151811061019657610196610bcc565b602002602001015161007d565b905060006101bd8460018151811061019657610196610bcc565b90506101d28282670de0b6b3a76400006103fa565b949350505050565b815160011415610200576101fa8260008151811061019657610196610bcc565b92915050565b919050565b600063ffffffff821661029257826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561024b57600080fd5b505afa15801561025f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102839190610bf4565b509495506101fa945050505050565b6040805160028082526060820183526000926020830190803683370190505090506102be836001610c93565b816000815181106102d1576102d1610bcc565b602002602001019063ffffffff16908163ffffffff168152505060018160018151811061030057610300610bcc565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0386169063883bdbfd90610344908590600401610cbb565b60006040518083038186803b15801561035c57600080fd5b505afa158015610370573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103989190810190610d74565b5090506103f18460030b826000815181106103b5576103b5610bcc565b6020026020010151836001815181106103d0576103d0610bcc565b60200260200101516103e29190610e40565b6103ec9190610e90565b610576565b95945050505050565b600080806000198587098587029250828110838203039150508060001415610434576000841161042957600080fd5b50829004905061056f565b80841161044057600080fd5b60008486880980840393811190920391905060008561046181196001610ece565b169586900495938490049360008190030460010190506104818184610b83565b909317926000610492876003610b83565b60021890506104a18188610b83565b6104ac906002610ee6565b6104b69082610b83565b90506104c28188610b83565b6104cd906002610ee6565b6104d79082610b83565b90506104e38188610b83565b6104ee906002610ee6565b6104f89082610b83565b90506105048188610b83565b61050f906002610ee6565b6105199082610b83565b90506105258188610b83565b610530906002610ee6565b61053a9082610b83565b90506105468188610b83565b610551906002610ee6565b61055b9082610b83565b90506105678186610b83565b955050505050505b9392505050565b60008060008360020b1261058d578260020b61059a565b8260020b61059a90610efd565b90506105a9620d89e719610f1a565b62ffffff168111156105e15760405162461bcd60e51b81526020600482015260016024820152601560fa1b604482015260640161016b565b6000600182166105f557600160801b610607565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610646576080610641826ffff97272373d413259a46990580e213a610b83565b901c90505b600482161561067057608061066b826ffff2e50f5f656932ef12357cf3c7fdcc610b83565b901c90505b600882161561069a576080610695826fffe5caca7e10e4e61c3624eaa0941cd0610b83565b901c90505b60108216156106c45760806106bf826fffcb9843d60f6159c9db58835c926644610b83565b901c90505b60208216156106ee5760806106e9826fff973b41fa98c081472e6896dfb254c0610b83565b901c90505b6040821615610718576080610713826fff2ea16466c96a3843ec78b326b52861610b83565b901c90505b608082161561074257608061073d826ffe5dee046a99a2a811c461f1969c3053610b83565b901c90505b61010082161561076d576080610768826ffcbe86c7900a88aedcffc83b479aa3a4610b83565b901c90505b610200821615610798576080610793826ff987a7253ac413176f2b074cf7815e54610b83565b901c90505b6104008216156107c35760806107be826ff3392b0822b70005940c7a398e4b70f3610b83565b901c90505b6108008216156107ee5760806107e9826fe7159475a2c29b7443b29c7fa6e889d9610b83565b901c90505b611000821615610819576080610814826fd097f3bdfd2022b8845ad8f792aa5825610b83565b901c90505b61200082161561084457608061083f826fa9f746462d870fdf8a65dc1f90e061e5610b83565b901c90505b61400082161561086f57608061086a826f70d869a156d2a1b890bb3df62baf32f7610b83565b901c90505b61800082161561089a576080610895826f31be135f97d08fd981231505542fcfa6610b83565b901c90505b620100008216156108c65760806108c1826f09aa508b5b7a84e1c677de54f3e99bc9610b83565b901c90505b620200008216156108f15760806108ec826e5d6af8dedb81196699c329225ee604610b83565b901c90505b6204000082161561091b576080610916826d2216e584f5fa1ea926041bedfe98610b83565b901c90505b6208000082161561094357608061093e826b048a170391f7dc42444e8fa2610b83565b901c90505b60008460020b131561095e5761095b81600019610bb8565b90505b61096d64010000000082610f3d565b1561097957600161097c565b60005b6101d29060ff16602083901c610ece565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109cc576109cc61098d565b604052919050565b6001600160a01b03811681146109e957600080fd5b50565b80151581146109e957600080fd5b600060a08284031215610a0c57600080fd5b60405160a0810181811067ffffffffffffffff82111715610a2f57610a2f61098d565b6040529050808235610a40816109d4565b81526020830135610a50816109ec565b6020820152604083013563ffffffff81168114610a6c57600080fd5b8060408301525060608301356060820152608083013560808201525092915050565b600060a08284031215610aa057600080fd5b61056f83836109fa565b600067ffffffffffffffff821115610ac457610ac461098d565b5060051b60200190565b60006020808385031215610ae157600080fd5b823567ffffffffffffffff811115610af857600080fd5b8301601f81018513610b0957600080fd5b8035610b1c610b1782610aaa565b6109a3565b81815260a09182028301840191848201919088841115610b3b57600080fd5b938501935b83851015610b6157610b5289866109fa565b83529384019391850191610b40565b50979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610b9d57610b9d610b6d565b500290565b634e487b7160e01b600052601260045260246000fd5b600082610bc757610bc7610ba2565b500490565b634e487b7160e01b600052603260045260246000fd5b805161ffff8116811461020057600080fd5b600080600080600080600060e0888a031215610c0f57600080fd5b8751610c1a816109d4565b8097505060208801518060020b8114610c3257600080fd5b9550610c4060408901610be2565b9450610c4e60608901610be2565b9350610c5c60808901610be2565b925060a088015160ff81168114610c7257600080fd5b60c0890151909250610c83816109ec565b8091505092959891949750929550565b600063ffffffff808316818516808303821115610cb257610cb2610b6d565b01949350505050565b6020808252825182820181905260009190848201906040850190845b81811015610cf957835163ffffffff1683529284019291840191600101610cd7565b50909695505050505050565b600082601f830112610d1657600080fd5b81516020610d26610b1783610aaa565b82815260059290921b84018101918181019086841115610d4557600080fd5b8286015b84811015610d69578051610d5c816109d4565b8352918301918301610d49565b509695505050505050565b60008060408385031215610d8757600080fd5b825167ffffffffffffffff80821115610d9f57600080fd5b818501915085601f830112610db357600080fd5b81516020610dc3610b1783610aaa565b82815260059290921b84018101918181019089841115610de257600080fd5b948201945b83861015610e105785518060060b8114610e015760008081fd5b82529482019490820190610de7565b91880151919650909350505080821115610e2957600080fd5b50610e3685828601610d05565b9150509250929050565b60008160060b8360060b6000811281667fffffffffffff1901831281151615610e6b57610e6b610b6d565b81667fffffffffffff018313811615610e8657610e86610b6d565b5090039392505050565b60008160060b8360060b80610ea757610ea7610ba2565b667fffffffffffff19821460001982141615610ec557610ec5610b6d565b90059392505050565b60008219821115610ee157610ee1610b6d565b500190565b600082821015610ef857610ef8610b6d565b500390565b6000600160ff1b821415610f1357610f13610b6d565b5060000390565b60008160020b627fffff19811415610f3457610f34610b6d565b60000392915050565b600082610f4c57610f4c610ba2565b50069056fea2646970667358221220a3510e361726cb15bfcf40c4cedef84f1b2d4fcb803fb69d338beac2206b8a0c64736f6c63430008090033", + "numDeployments": 2, + "solcInputHash": "2fbfd407212128842c1766ec39678e5a", + "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"zeroForOne\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"twapInterval\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"token0Decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Decimals\",\"type\":\"uint256\"}],\"internalType\":\"struct IUniswapPricingLibrary.PoolRouteConfig\",\"name\":\"_poolRouteConfig\",\"type\":\"tuple\"}],\"name\":\"getUniswapPriceRatioForPool\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"priceRatio\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"zeroForOne\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"twapInterval\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"token0Decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"token1Decimals\",\"type\":\"uint256\"}],\"internalType\":\"struct IUniswapPricingLibrary.PoolRouteConfig[]\",\"name\":\"poolRoutes\",\"type\":\"tuple[]\"}],\"name\":\"getUniswapPriceRatioForPoolRoutes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"priceRatio\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/UniswapPricingLibrary.sol\":\"UniswapPricingLibrary\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/ContextUpgradeable.sol\\\";\\nimport \\\"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\\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 function __Ownable_init() internal onlyInitializing {\\n __Ownable_init_unchained();\\n }\\n\\n function __Ownable_init_unchained() internal onlyInitializing {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\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 the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n}\\n\",\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/AddressUpgradeable.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0x037c334add4b033ad3493038c25be1682d78c00992e1acb0e2795caff3925271\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (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 IERC20Upgradeable {\\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 /**\\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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x4e733d3164f73f461eaf9d8087a7ad1ea180bdc8ba0d3d61b0e1ae16d8e63dff\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20Upgradeable.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x605434219ebbe4653f703640f06969faa5a1d78f0bfef878e5ddbb1ca369ceeb\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary AddressUpgradeable {\\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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or 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 _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\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\",\"keccak256\":\"0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\nimport \\\"../proxy/utils/Initializable.sol\\\";\\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 ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\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 /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\",\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev These functions deal with verification of Merkle Tree proofs.\\n *\\n * The tree and the proofs can be generated using our\\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\\n * You will find a quickstart guide in the readme.\\n *\\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\\n * hashing, or use a hash function other than keccak256 for hashing leaves.\\n * This is because the concatenation of a sorted pair of internal nodes in\\n * the merkle tree could be reinterpreted as a leaf value.\\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\\n * against this attack out of the box.\\n */\\nlibrary MerkleProofUpgradeable {\\n /**\\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\\n * defined by `root`. For this, a `proof` must be provided, containing\\n * sibling hashes on the branch from the leaf to the root of the tree. Each\\n * pair of leaves and each pair of pre-images are assumed to be sorted.\\n */\\n function verify(\\n bytes32[] memory proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProof(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {verify}\\n *\\n * _Available since v4.7._\\n */\\n function verifyCalldata(\\n bytes32[] calldata proof,\\n bytes32 root,\\n bytes32 leaf\\n ) internal pure returns (bool) {\\n return processProofCalldata(proof, leaf) == root;\\n }\\n\\n /**\\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\\n * hash matches the root of the tree. When processing the proof, the pairs\\n * of leafs & pre-images are assumed to be sorted.\\n *\\n * _Available since v4.4._\\n */\\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Calldata version of {processProof}\\n *\\n * _Available since v4.7._\\n */\\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\\n bytes32 computedHash = leaf;\\n for (uint256 i = 0; i < proof.length; i++) {\\n computedHash = _hashPair(computedHash, proof[i]);\\n }\\n return computedHash;\\n }\\n\\n /**\\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerify(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProof(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Calldata version of {multiProofVerify}\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function multiProofVerifyCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32 root,\\n bytes32[] memory leaves\\n ) internal pure returns (bool) {\\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\\n }\\n\\n /**\\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\\n * respectively.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProof(\\n bytes32[] memory proof,\\n bool[] memory proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value for the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n return hashes[totalHashes - 1];\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n /**\\n * @dev Calldata version of {processMultiProof}.\\n *\\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\\n *\\n * _Available since v4.7._\\n */\\n function processMultiProofCalldata(\\n bytes32[] calldata proof,\\n bool[] calldata proofFlags,\\n bytes32[] memory leaves\\n ) internal pure returns (bytes32 merkleRoot) {\\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\\n // the merkle tree.\\n uint256 leavesLen = leaves.length;\\n uint256 totalHashes = proofFlags.length;\\n\\n // Check proof validity.\\n require(leavesLen + proof.length - 1 == totalHashes, \\\"MerkleProof: invalid multiproof\\\");\\n\\n // The xxxPos values are \\\"pointers\\\" to the next value to consume in each array. All accesses are done using\\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \\\"pop\\\".\\n bytes32[] memory hashes = new bytes32[](totalHashes);\\n uint256 leafPos = 0;\\n uint256 hashPos = 0;\\n uint256 proofPos = 0;\\n // At each step, we compute the next hash using two values:\\n // - a value from the \\\"main queue\\\". If not all leaves have been consumed, we get the next leaf, otherwise we\\n // get the next hash.\\n // - depending on the flag, either another value for the \\\"main queue\\\" (merging branches) or an element from the\\n // `proof` array.\\n for (uint256 i = 0; i < totalHashes; i++) {\\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\\n hashes[i] = _hashPair(a, b);\\n }\\n\\n if (totalHashes > 0) {\\n return hashes[totalHashes - 1];\\n } else if (leavesLen > 0) {\\n return leaves[0];\\n } else {\\n return proof[0];\\n }\\n }\\n\\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\\n }\\n\\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, a)\\n mstore(0x20, b)\\n value := keccak256(0x00, 0x40)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x1741ea24897cdf435d3a476e9d9280b8be58a435dacb6997d54a2aa657446e5a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary MathUpgradeable {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\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 return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\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\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\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 /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc1bd5b53319c68f84e3becd75694d941e8f4be94049903232cd8bc7c535aaa5a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSetUpgradeable {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x4807db844a856813048b5af81a764fdd25a0ae8876a3132593e8d21ddc6b607c\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (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 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 /**\\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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\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 return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\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\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\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 /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\"},\"contracts/interfaces/IUniswapPricingLibrary.sol\":{\"content\":\"// SPDX-Licence-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\n\\ninterface IUniswapPricingLibrary {\\n \\n\\n struct PoolRouteConfig {\\n address pool;\\n bool zeroForOne;\\n uint32 twapInterval;\\n uint256 token0Decimals;\\n uint256 token1Decimals;\\n } \\n\\n\\n\\n function getUniswapPriceRatioForPoolRoutes(\\n PoolRouteConfig[] memory poolRoutes\\n ) external view returns (uint256 priceRatio);\\n\\n\\n function getUniswapPriceRatioForPool(\\n PoolRouteConfig memory poolRoute\\n ) external view returns (uint256 priceRatio);\\n\\n}\\n\",\"keccak256\":\"0xaac4c07c82618cc01b41d56d57b52cf134afdc2220115ccc1744adfc475c2583\"},\"contracts/interfaces/uniswap/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\nimport \\\"./pool/IUniswapV3PoolImmutables.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolState.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolDerivedState.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolActions.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolOwnerActions.sol\\\";\\nimport \\\"./pool/IUniswapV3PoolEvents.sol\\\";\\n\\n/// @title The interface for a Uniswap V3 Pool\\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\\n/// to the ERC20 specification\\n/// @dev The pool interface is broken up into many smaller pieces\\ninterface IUniswapV3Pool is\\n IUniswapV3PoolImmutables,\\n IUniswapV3PoolState,\\n IUniswapV3PoolDerivedState,\\n IUniswapV3PoolActions,\\n IUniswapV3PoolOwnerActions,\\n IUniswapV3PoolEvents\\n{\\n\\n}\\n\",\"keccak256\":\"0xb3ab192db0227b3253579f34b108af8c91c6b54bfe805fa59f11abdcb13e87fa\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissionless pool actions\\n/// @notice Contains pool methods that can be called by anyone\\ninterface IUniswapV3PoolActions {\\n /// @notice Sets the initial price for the pool\\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\\n function initialize(uint160 sqrtPriceX96) external;\\n\\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\\n /// @param recipient The address for which the liquidity will be created\\n /// @param tickLower The lower tick of the position in which to add liquidity\\n /// @param tickUpper The upper tick of the position in which to add liquidity\\n /// @param amount The amount of liquidity to mint\\n /// @param data Any data that should be passed through to the callback\\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\\n function mint(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount,\\n bytes calldata data\\n ) external returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Collects tokens owed to a position\\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\\n /// @param recipient The address which should receive the fees collected\\n /// @param tickLower The lower tick of the position for which to collect fees\\n /// @param tickUpper The upper tick of the position for which to collect fees\\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\\n /// @return amount0 The amount of fees collected in token0\\n /// @return amount1 The amount of fees collected in token1\\n function collect(\\n address recipient,\\n int24 tickLower,\\n int24 tickUpper,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n\\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\\n /// @dev Fees must be collected separately via a call to #collect\\n /// @param tickLower The lower tick of the position for which to burn liquidity\\n /// @param tickUpper The upper tick of the position for which to burn liquidity\\n /// @param amount How much liquidity to burn\\n /// @return amount0 The amount of token0 sent to the recipient\\n /// @return amount1 The amount of token1 sent to the recipient\\n function burn(int24 tickLower, int24 tickUpper, uint128 amount)\\n external\\n returns (uint256 amount0, uint256 amount1);\\n\\n /// @notice Swap token0 for token1, or token1 for token0\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\\n /// @param recipient The address to receive the output of the swap\\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\\n /// @param data Any data to be passed through to the callback\\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n\\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\\n /// @param recipient The address which will receive the token0 and token1 amounts\\n /// @param amount0 The amount of token0 to send\\n /// @param amount1 The amount of token1 to send\\n /// @param data Any data to be passed through to the callback\\n function flash(\\n address recipient,\\n uint256 amount0,\\n uint256 amount1,\\n bytes calldata data\\n ) external;\\n\\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\\n /// the input observationCardinalityNext.\\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\\n function increaseObservationCardinalityNext(\\n uint16 observationCardinalityNext\\n ) external;\\n}\\n\",\"keccak256\":\"0x0d71eeba27d612d047b327e34231360e4e0014d0241e791e5ad62fb40a1a73b3\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolDerivedState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that is not stored\\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\\n/// blockchain. The functions here may have variable gas costs.\\ninterface IUniswapV3PoolDerivedState {\\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\\n /// you must call it with secondsAgos = [3600, 0].\\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\\n /// timestamp\\n function observe(uint32[] calldata secondsAgos)\\n external\\n view\\n returns (\\n int56[] memory tickCumulatives,\\n uint160[] memory secondsPerLiquidityCumulativeX128s\\n );\\n\\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\\n /// snapshot is taken and the second snapshot is taken.\\n /// @param tickLower The lower tick of the range\\n /// @param tickUpper The upper tick of the range\\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\\n /// @return secondsInside The snapshot of seconds per liquidity for the range\\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\\n external\\n view\\n returns (\\n int56 tickCumulativeInside,\\n uint160 secondsPerLiquidityInsideX128,\\n uint32 secondsInside\\n );\\n}\\n\",\"keccak256\":\"0x75a1cde36f8d8e785df6b61c2b87c9a25f1a7bf05567bd490f021113286c7966\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolEvents.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Events emitted by a pool\\n/// @notice Contains all events emitted by the pool\\ninterface IUniswapV3PoolEvents {\\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\\n event Initialize(uint160 sqrtPriceX96, int24 tick);\\n\\n /// @notice Emitted when liquidity is minted for a given position\\n /// @param sender The address that minted the liquidity\\n /// @param owner The owner of the position and recipient of any minted liquidity\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity minted to the position range\\n /// @param amount0 How much token0 was required for the minted liquidity\\n /// @param amount1 How much token1 was required for the minted liquidity\\n event Mint(\\n address sender,\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted when fees are collected by the owner of a position\\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\\n /// @param owner The owner of the position for which fees are collected\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount0 The amount of token0 fees collected\\n /// @param amount1 The amount of token1 fees collected\\n event Collect(\\n address indexed owner,\\n address recipient,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount0,\\n uint128 amount1\\n );\\n\\n /// @notice Emitted when a position's liquidity is removed\\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\\n /// @param owner The owner of the position for which liquidity is removed\\n /// @param tickLower The lower tick of the position\\n /// @param tickUpper The upper tick of the position\\n /// @param amount The amount of liquidity to remove\\n /// @param amount0 The amount of token0 withdrawn\\n /// @param amount1 The amount of token1 withdrawn\\n event Burn(\\n address indexed owner,\\n int24 indexed tickLower,\\n int24 indexed tickUpper,\\n uint128 amount,\\n uint256 amount0,\\n uint256 amount1\\n );\\n\\n /// @notice Emitted by the pool for any swaps between token0 and token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the output of the swap\\n /// @param amount0 The delta of the token0 balance of the pool\\n /// @param amount1 The delta of the token1 balance of the pool\\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\\n /// @param liquidity The liquidity of the pool after the swap\\n /// @param tick The log base 1.0001 of price of the pool after the swap\\n event Swap(\\n address indexed sender,\\n address indexed recipient,\\n int256 amount0,\\n int256 amount1,\\n uint160 sqrtPriceX96,\\n uint128 liquidity,\\n int24 tick\\n );\\n\\n /// @notice Emitted by the pool for any flashes of token0/token1\\n /// @param sender The address that initiated the swap call, and that received the callback\\n /// @param recipient The address that received the tokens from flash\\n /// @param amount0 The amount of token0 that was flashed\\n /// @param amount1 The amount of token1 that was flashed\\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\\n event Flash(\\n address indexed sender,\\n address indexed recipient,\\n uint256 amount0,\\n uint256 amount1,\\n uint256 paid0,\\n uint256 paid1\\n );\\n\\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\\n /// just before a mint/swap/burn.\\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\\n event IncreaseObservationCardinalityNext(\\n uint16 observationCardinalityNextOld,\\n uint16 observationCardinalityNextNew\\n );\\n\\n /// @notice Emitted when the protocol fee is changed by the pool\\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\\n /// @param feeProtocol0New The updated value of the token0 protocol fee\\n /// @param feeProtocol1New The updated value of the token1 protocol fee\\n event SetFeeProtocol(\\n uint8 feeProtocol0Old,\\n uint8 feeProtocol1Old,\\n uint8 feeProtocol0New,\\n uint8 feeProtocol1New\\n );\\n\\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\\n /// @param sender The address that collects the protocol fees\\n /// @param recipient The address that receives the collected protocol fees\\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\\n event CollectProtocol(\\n address indexed sender,\\n address indexed recipient,\\n uint128 amount0,\\n uint128 amount1\\n );\\n}\\n\",\"keccak256\":\"0x7209000762e515eceabd42bc2660497d91dfa33099f99d8fc3c55dd1b9578744\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolImmutables.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that never changes\\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\\ninterface IUniswapV3PoolImmutables {\\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\\n /// @return The contract address\\n function factory() external view returns (address);\\n\\n /// @notice The first of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token0() external view returns (address);\\n\\n /// @notice The second of the two tokens of the pool, sorted by address\\n /// @return The token contract address\\n function token1() external view returns (address);\\n\\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\\n /// @return The fee\\n function fee() external view returns (uint24);\\n\\n /// @notice The pool tick spacing\\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\\n /// This value is an int24 to avoid casting even though it is always positive.\\n /// @return The tick spacing\\n function tickSpacing() external view returns (int24);\\n\\n /// @notice The maximum amount of position liquidity that can use any tick in the range\\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\\n /// @return The max amount of liquidity per tick\\n function maxLiquidityPerTick() external view returns (uint128);\\n}\\n\",\"keccak256\":\"0xf6e5d2cd1139c4c276bdbc8e1d2b256e456c866a91f1b868da265c6d2685c3f7\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolOwnerActions.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Permissioned pool actions\\n/// @notice Contains pool methods that may only be called by the factory owner\\ninterface IUniswapV3PoolOwnerActions {\\n /// @notice Set the denominator of the protocol's % share of the fees\\n /// @param feeProtocol0 new protocol fee for token0 of the pool\\n /// @param feeProtocol1 new protocol fee for token1 of the pool\\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\\n\\n /// @notice Collect the protocol fee accrued to the pool\\n /// @param recipient The address to which collected protocol fees should be sent\\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\\n /// @return amount0 The protocol fee collected in token0\\n /// @return amount1 The protocol fee collected in token1\\n function collectProtocol(\\n address recipient,\\n uint128 amount0Requested,\\n uint128 amount1Requested\\n ) external returns (uint128 amount0, uint128 amount1);\\n}\\n\",\"keccak256\":\"0x759b78a2918af9e99e246dc3af084f654e48ef32bb4e4cb8a966aa3dcaece235\",\"license\":\"GPL-2.0-or-later\"},\"contracts/interfaces/uniswap/pool/IUniswapV3PoolState.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.5.0;\\n\\n/// @title Pool state that can change\\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\\n/// per transaction\\ninterface IUniswapV3PoolState {\\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\\n /// when accessed externally.\\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\\n /// boundary.\\n /// observationIndex The index of the last oracle observation that was written,\\n /// observationCardinality The current maximum number of observations stored in the pool,\\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\\n /// feeProtocol The protocol fee for both tokens of the pool.\\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\\n /// unlocked Whether the pool is currently locked to reentrancy\\n function slot0()\\n external\\n view\\n returns (\\n uint160 sqrtPriceX96,\\n int24 tick,\\n uint16 observationIndex,\\n uint16 observationCardinality,\\n uint16 observationCardinalityNext,\\n uint8 feeProtocol,\\n bool unlocked\\n );\\n\\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal0X128() external view returns (uint256);\\n\\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\\n /// @dev This value can overflow the uint256\\n function feeGrowthGlobal1X128() external view returns (uint256);\\n\\n /// @notice The amounts of token0 and token1 that are owed to the protocol\\n /// @dev Protocol fees will never exceed uint128 max in either token\\n function protocolFees()\\n external\\n view\\n returns (uint128 token0, uint128 token1);\\n\\n /// @notice The currently in range liquidity available to the pool\\n /// @dev This value has no relationship to the total liquidity across all ticks\\n function liquidity() external view returns (uint128);\\n\\n /// @notice Look up information about a specific tick in the pool\\n /// @param tick The tick to look up\\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\\n /// tick upper,\\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\\n /// a specific position.\\n function ticks(int24 tick)\\n external\\n view\\n returns (\\n uint128 liquidityGross,\\n int128 liquidityNet,\\n uint256 feeGrowthOutside0X128,\\n uint256 feeGrowthOutside1X128,\\n int56 tickCumulativeOutside,\\n uint160 secondsPerLiquidityOutsideX128,\\n uint32 secondsOutside,\\n bool initialized\\n );\\n\\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\\n function tickBitmap(int16 wordPosition) external view returns (uint256);\\n\\n /// @notice Returns the information about a position by the position's key\\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\\n /// @return _liquidity The amount of liquidity in the position,\\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\\n function positions(bytes32 key)\\n external\\n view\\n returns (\\n uint128 _liquidity,\\n uint256 feeGrowthInside0LastX128,\\n uint256 feeGrowthInside1LastX128,\\n uint128 tokensOwed0,\\n uint128 tokensOwed1\\n );\\n\\n /// @notice Returns data about a specific observation index\\n /// @param index The element of the observations array to fetch\\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\\n /// ago, rather than at a specific index in the array.\\n /// @return blockTimestamp The timestamp of the observation,\\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\\n /// Returns initialized whether the observation has been initialized and the values are safe to use\\n function observations(uint256 index)\\n external\\n view\\n returns (\\n uint32 blockTimestamp,\\n int56 tickCumulative,\\n uint160 secondsPerLiquidityCumulativeX128,\\n bool initialized\\n );\\n}\\n\",\"keccak256\":\"0x29867ae7524b2ae6581b95abf0c1dd1f697f0494d4c333058a00cdb215f83a43\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/UniswapPricingLibrary.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\n \\n\\nimport {IUniswapPricingLibrary} from \\\"../interfaces/IUniswapPricingLibrary.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\n \\nimport \\\"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\\\";\\n\\n// Libraries\\nimport { MathUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\\\";\\nimport \\\"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\\\";\\n\\nimport \\\"../interfaces/uniswap/IUniswapV3Pool.sol\\\"; \\n\\nimport \\\"../libraries/uniswap/TickMath.sol\\\";\\nimport \\\"../libraries/uniswap/FixedPoint96.sol\\\";\\nimport \\\"../libraries/uniswap/FullMath.sol\\\";\\n \\n \\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\n\\n\\n/*\\n\\nOnly do decimal expansion if it is an ERC20 not anything else !! \\n\\n*/\\n\\nlibrary UniswapPricingLibrary \\n{\\n \\n uint256 constant STANDARD_EXPANSION_FACTOR = 1e18;\\n\\n function getUniswapPriceRatioForPoolRoutes(\\n IUniswapPricingLibrary.PoolRouteConfig[] memory poolRoutes\\n ) public view returns (uint256 priceRatio) {\\n require(poolRoutes.length <= 2, \\\"invalid pool routes length\\\");\\n\\n if (poolRoutes.length == 2) {\\n uint256 pool0PriceRatio = getUniswapPriceRatioForPool(\\n poolRoutes[0]\\n );\\n\\n uint256 pool1PriceRatio = getUniswapPriceRatioForPool(\\n poolRoutes[1]\\n );\\n\\n return\\n FullMath.mulDiv(\\n pool0PriceRatio,\\n pool1PriceRatio,\\n STANDARD_EXPANSION_FACTOR\\n );\\n } else if (poolRoutes.length == 1) {\\n return getUniswapPriceRatioForPool(poolRoutes[0]);\\n }\\n\\n //else return 0\\n }\\n\\n /*\\n The resultant product is expanded by STANDARD_EXPANSION_FACTOR one time \\n */\\n function getUniswapPriceRatioForPool(\\n IUniswapPricingLibrary.PoolRouteConfig memory _poolRouteConfig\\n ) public view returns (uint256 priceRatio) {\\n uint160 sqrtPriceX96 = getSqrtTwapX96(\\n _poolRouteConfig.pool,\\n _poolRouteConfig.twapInterval\\n );\\n\\n //This is the token 1 per token 0 price\\n uint256 sqrtPrice = FullMath.mulDiv(\\n sqrtPriceX96,\\n STANDARD_EXPANSION_FACTOR,\\n 2**96\\n );\\n\\n uint256 sqrtPriceInverse = (STANDARD_EXPANSION_FACTOR *\\n STANDARD_EXPANSION_FACTOR) / sqrtPrice;\\n\\n uint256 price = _poolRouteConfig.zeroForOne\\n ? sqrtPrice * sqrtPrice\\n : sqrtPriceInverse * sqrtPriceInverse;\\n\\n return price / STANDARD_EXPANSION_FACTOR;\\n }\\n\\n\\n\\n function getSqrtTwapX96(address uniswapV3Pool, uint32 twapInterval)\\n internal\\n view\\n returns (uint160 sqrtPriceX96)\\n {\\n if (twapInterval == 0) {\\n // return the current price if twapInterval == 0\\n (sqrtPriceX96, , , , , , ) = IUniswapV3Pool(uniswapV3Pool).slot0();\\n } else {\\n uint32[] memory secondsAgos = new uint32[](2);\\n secondsAgos[0] = twapInterval + 1; // from (before)\\n secondsAgos[1] = 1; // one block prior\\n\\n (int56[] memory tickCumulatives, ) = IUniswapV3Pool(uniswapV3Pool)\\n .observe(secondsAgos);\\n\\n // tick(imprecise as it's an integer) to price\\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(\\n int24(\\n (tickCumulatives[1] - tickCumulatives[0]) /\\n int32(twapInterval)\\n )\\n );\\n }\\n }\\n\\n function getPriceX96FromSqrtPriceX96(uint160 sqrtPriceX96)\\n internal\\n pure\\n returns (uint256 priceX96)\\n { \\n\\n \\n return FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96);\\n }\\n\\n}\",\"keccak256\":\"0x89fa90d3bba54e357a693f9e0ea96920edfd60c16f8a6a77a32892f4cafd60f3\",\"license\":\"MIT\"},\"contracts/libraries/uniswap/FixedPoint96.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity >=0.4.0;\\n\\n/// @title FixedPoint96\\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\\n/// @dev Used in SqrtPriceMath.sol\\nlibrary FixedPoint96 {\\n uint8 internal constant RESOLUTION = 96;\\n uint256 internal constant Q96 = 0x1000000000000000000000000;\\n}\\n\",\"keccak256\":\"0x0ba8a9b95a956a4050749c0158e928398c447c91469682ca8a7cc7e77a7fe032\",\"license\":\"GPL-2.0-or-later\"},\"contracts/libraries/uniswap/FullMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title Contains 512-bit math functions\\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\\n/// @dev Handles \\\"phantom overflow\\\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\\nlibrary FullMath {\\n /// @notice Calculates floor(a\\u00d7b\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n /// @param a The multiplicand\\n /// @param b The multiplier\\n /// @param denominator The divisor\\n /// @return result The 256-bit result\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\\n function mulDiv(uint256 a, uint256 b, uint256 denominator)\\n internal\\n pure\\n returns (uint256 result)\\n {\\n // 512-bit multiply [prod1 prod0] = a * b\\n // Compute the product mod 2**256 and mod 2**256 - 1\\n // then use the Chinese Remainder Theorem to reconstruct\\n // 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(a, b, not(0))\\n prod0 := mul(a, b)\\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 require(denominator > 0);\\n assembly {\\n result := div(prod0, denominator)\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2**256.\\n // Also prevents denominator == 0\\n require(denominator > prod1);\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0]\\n // Compute remainder using mulmod\\n uint256 remainder;\\n assembly {\\n remainder := mulmod(a, b, denominator)\\n }\\n // Subtract 256 bit number from 512 bit number\\n assembly {\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator\\n // Compute largest power of two divisor of denominator.\\n // Always >= 1.\\n // uint256 twos = -denominator & denominator;\\n uint256 twos = (~denominator + 1) & denominator;\\n // Divide denominator by power of two\\n assembly {\\n denominator := div(denominator, twos)\\n }\\n\\n // Divide [prod1 prod0] by the factors of two\\n assembly {\\n prod0 := div(prod0, twos)\\n }\\n // Shift in bits from prod1 into prod0. For this we need\\n // to flip `twos` such that it is 2**256 / twos.\\n // If twos is zero, then it becomes one\\n assembly {\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2**256\\n // Now that denominator is an odd number, it has an inverse\\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\\n // Compute the inverse by starting with a seed that is correct\\n // correct for four bits. That is, denominator * inv = 1 mod 2**4\\n uint256 inv = (3 * denominator) ^ 2;\\n // Now use Newton-Raphson iteration to improve the precision.\\n // Thanks to Hensel's lifting lemma, this also works in modular\\n // arithmetic, doubling the correct bits in each step.\\n inv *= 2 - denominator * inv; // inverse mod 2**8\\n inv *= 2 - denominator * inv; // inverse mod 2**16\\n inv *= 2 - denominator * inv; // inverse mod 2**32\\n inv *= 2 - denominator * inv; // inverse mod 2**64\\n inv *= 2 - denominator * inv; // inverse mod 2**128\\n inv *= 2 - denominator * inv; // inverse mod 2**256\\n\\n // Because the division is now exact we can divide by multiplying\\n // with the modular inverse of denominator. This will give us the\\n // correct result modulo 2**256. Since the precoditions guarantee\\n // that the outcome is less than 2**256, this is the final result.\\n // We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inv;\\n return result;\\n }\\n\\n /// @notice Calculates ceil(a\\u00d7b\\u00f7denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n /// @param a The multiplicand\\n /// @param b The multiplier\\n /// @param denominator The divisor\\n /// @return result The 256-bit result\\n function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator)\\n internal\\n pure\\n returns (uint256 result)\\n {\\n result = mulDiv(a, b, denominator);\\n if (mulmod(a, b, denominator) > 0) {\\n require(result < type(uint256).max);\\n result++;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfb50b2e1fa576851562dd6cebc786506f40f69097955e7c9e3d501899b90c8cd\",\"license\":\"MIT\"},\"contracts/libraries/uniswap/TickMath.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\npragma solidity ^0.8.0;\\n\\n/// @title Math library for computing sqrt prices from ticks and vice versa\\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\\n/// prices between 2**-128 and 2**128\\nlibrary TickMath {\\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\\n int24 internal constant MIN_TICK = -887272;\\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\\n int24 internal constant MAX_TICK = -MIN_TICK;\\n\\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\n uint160 internal constant MAX_SQRT_RATIO =\\n 1461446703485210103287273052203988822378723970342;\\n\\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\\n /// @dev Throws if |tick| > max tick\\n /// @param tick The input tick for the above formula\\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\\n /// at the given tick\\n function getSqrtRatioAtTick(int24 tick)\\n internal\\n pure\\n returns (uint160 sqrtPriceX96)\\n {\\n uint256 absTick = tick < 0\\n ? uint256(-int256(tick))\\n : uint256(int256(tick));\\n require(absTick <= uint256(uint24(MAX_TICK)), \\\"T\\\");\\n\\n uint256 ratio = absTick & 0x1 != 0\\n ? 0xfffcb933bd6fad37aa2d162d1a594001\\n : 0x100000000000000000000000000000000;\\n if (absTick & 0x2 != 0)\\n ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\\n if (absTick & 0x4 != 0)\\n ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\\n if (absTick & 0x8 != 0)\\n ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\\n if (absTick & 0x10 != 0)\\n ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\\n if (absTick & 0x20 != 0)\\n ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\\n if (absTick & 0x40 != 0)\\n ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\\n if (absTick & 0x80 != 0)\\n ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\\n if (absTick & 0x100 != 0)\\n ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\\n if (absTick & 0x200 != 0)\\n ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\\n if (absTick & 0x400 != 0)\\n ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\\n if (absTick & 0x800 != 0)\\n ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\\n if (absTick & 0x1000 != 0)\\n ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\\n if (absTick & 0x2000 != 0)\\n ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\\n if (absTick & 0x4000 != 0)\\n ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\\n if (absTick & 0x8000 != 0)\\n ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\\n if (absTick & 0x10000 != 0)\\n ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\\n if (absTick & 0x20000 != 0)\\n ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\\n if (absTick & 0x40000 != 0)\\n ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\\n if (absTick & 0x80000 != 0)\\n ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\\n\\n if (tick > 0) ratio = type(uint256).max / ratio;\\n\\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\\n sqrtPriceX96 = uint160(\\n (ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)\\n );\\n }\\n\\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\\n /// ever return.\\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\\n function getTickAtSqrtRatio(uint160 sqrtPriceX96)\\n internal\\n pure\\n returns (int24 tick)\\n {\\n // second inequality must be < because the price can never reach the price at the max tick\\n require(\\n sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO,\\n \\\"R\\\"\\n );\\n uint256 ratio = uint256(sqrtPriceX96) << 32;\\n\\n uint256 r = ratio;\\n uint256 msb = 0;\\n\\n assembly {\\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(5, gt(r, 0xFFFFFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(4, gt(r, 0xFFFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(3, gt(r, 0xFF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(2, gt(r, 0xF))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := shl(1, gt(r, 0x3))\\n msb := or(msb, f)\\n r := shr(f, r)\\n }\\n assembly {\\n let f := gt(r, 0x1)\\n msb := or(msb, f)\\n }\\n\\n if (msb >= 128) r = ratio >> (msb - 127);\\n else r = ratio << (127 - msb);\\n\\n int256 log_2 = (int256(msb) - 128) << 64;\\n\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(63, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(62, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(61, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(60, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(59, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(58, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(57, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(56, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(55, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(54, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(53, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(52, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(51, f))\\n r := shr(f, r)\\n }\\n assembly {\\n r := shr(127, mul(r, r))\\n let f := shr(128, r)\\n log_2 := or(log_2, shl(50, f))\\n }\\n\\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\\n\\n int24 tickLow = int24(\\n (log_sqrt10001 - 3402992956809132418596140100660247210) >> 128\\n );\\n int24 tickHi = int24(\\n (log_sqrt10001 + 291339464771989622907027621153398088495) >> 128\\n );\\n\\n tick = tickLow == tickHi\\n ? tickLow\\n : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96\\n ? tickHi\\n : tickLow;\\n }\\n}\\n\",\"keccak256\":\"0xf98bbfc8977090f026ee4b8389bb1e2e903eb0575fceea10edb373f33d51d013\",\"license\":\"GPL-2.0-or-later\"}},\"version\":1}", + "bytecode": "0x610f8761003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80631217931b14610045578063caf0f0331461006a575b600080fd5b610058610053366004610a8e565b61007d565b60405190815260200160405180910390f35b610058610078366004610ace565b61011b565b60008061009283600001518460400151610205565b905060006100b6826001600160a01b0316670de0b6b3a7640000600160601b6103fa565b90506000816100cd670de0b6b3a764000080610b83565b6100d79190610bb8565b9050600085602001516100f3576100ee8280610b83565b6100fd565b6100fd8380610b83565b9050610111670de0b6b3a764000082610bb8565b9695505050505050565b60006002825111156101745760405162461bcd60e51b815260206004820152601a60248201527f696e76616c696420706f6f6c20726f75746573206c656e67746800000000000060448201526064015b60405180910390fd5b8151600214156101da5760006101a38360008151811061019657610196610bcc565b602002602001015161007d565b905060006101bd8460018151811061019657610196610bcc565b90506101d28282670de0b6b3a76400006103fa565b949350505050565b815160011415610200576101fa8260008151811061019657610196610bcc565b92915050565b919050565b600063ffffffff821661029257826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561024b57600080fd5b505afa15801561025f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102839190610bf4565b509495506101fa945050505050565b6040805160028082526060820183526000926020830190803683370190505090506102be836001610c93565b816000815181106102d1576102d1610bcc565b602002602001019063ffffffff16908163ffffffff168152505060018160018151811061030057610300610bcc565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0386169063883bdbfd90610344908590600401610cbb565b60006040518083038186803b15801561035c57600080fd5b505afa158015610370573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103989190810190610d74565b5090506103f18460030b826000815181106103b5576103b5610bcc565b6020026020010151836001815181106103d0576103d0610bcc565b60200260200101516103e29190610e40565b6103ec9190610e90565b610576565b95945050505050565b600080806000198587098587029250828110838203039150508060001415610434576000841161042957600080fd5b50829004905061056f565b80841161044057600080fd5b60008486880980840393811190920391905060008561046181196001610ece565b169586900495938490049360008190030460010190506104818184610b83565b909317926000610492876003610b83565b60021890506104a18188610b83565b6104ac906002610ee6565b6104b69082610b83565b90506104c28188610b83565b6104cd906002610ee6565b6104d79082610b83565b90506104e38188610b83565b6104ee906002610ee6565b6104f89082610b83565b90506105048188610b83565b61050f906002610ee6565b6105199082610b83565b90506105258188610b83565b610530906002610ee6565b61053a9082610b83565b90506105468188610b83565b610551906002610ee6565b61055b9082610b83565b90506105678186610b83565b955050505050505b9392505050565b60008060008360020b1261058d578260020b61059a565b8260020b61059a90610efd565b90506105a9620d89e719610f1a565b62ffffff168111156105e15760405162461bcd60e51b81526020600482015260016024820152601560fa1b604482015260640161016b565b6000600182166105f557600160801b610607565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610646576080610641826ffff97272373d413259a46990580e213a610b83565b901c90505b600482161561067057608061066b826ffff2e50f5f656932ef12357cf3c7fdcc610b83565b901c90505b600882161561069a576080610695826fffe5caca7e10e4e61c3624eaa0941cd0610b83565b901c90505b60108216156106c45760806106bf826fffcb9843d60f6159c9db58835c926644610b83565b901c90505b60208216156106ee5760806106e9826fff973b41fa98c081472e6896dfb254c0610b83565b901c90505b6040821615610718576080610713826fff2ea16466c96a3843ec78b326b52861610b83565b901c90505b608082161561074257608061073d826ffe5dee046a99a2a811c461f1969c3053610b83565b901c90505b61010082161561076d576080610768826ffcbe86c7900a88aedcffc83b479aa3a4610b83565b901c90505b610200821615610798576080610793826ff987a7253ac413176f2b074cf7815e54610b83565b901c90505b6104008216156107c35760806107be826ff3392b0822b70005940c7a398e4b70f3610b83565b901c90505b6108008216156107ee5760806107e9826fe7159475a2c29b7443b29c7fa6e889d9610b83565b901c90505b611000821615610819576080610814826fd097f3bdfd2022b8845ad8f792aa5825610b83565b901c90505b61200082161561084457608061083f826fa9f746462d870fdf8a65dc1f90e061e5610b83565b901c90505b61400082161561086f57608061086a826f70d869a156d2a1b890bb3df62baf32f7610b83565b901c90505b61800082161561089a576080610895826f31be135f97d08fd981231505542fcfa6610b83565b901c90505b620100008216156108c65760806108c1826f09aa508b5b7a84e1c677de54f3e99bc9610b83565b901c90505b620200008216156108f15760806108ec826e5d6af8dedb81196699c329225ee604610b83565b901c90505b6204000082161561091b576080610916826d2216e584f5fa1ea926041bedfe98610b83565b901c90505b6208000082161561094357608061093e826b048a170391f7dc42444e8fa2610b83565b901c90505b60008460020b131561095e5761095b81600019610bb8565b90505b61096d64010000000082610f3d565b1561097957600161097c565b60005b6101d29060ff16602083901c610ece565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109cc576109cc61098d565b604052919050565b6001600160a01b03811681146109e957600080fd5b50565b80151581146109e957600080fd5b600060a08284031215610a0c57600080fd5b60405160a0810181811067ffffffffffffffff82111715610a2f57610a2f61098d565b6040529050808235610a40816109d4565b81526020830135610a50816109ec565b6020820152604083013563ffffffff81168114610a6c57600080fd5b8060408301525060608301356060820152608083013560808201525092915050565b600060a08284031215610aa057600080fd5b61056f83836109fa565b600067ffffffffffffffff821115610ac457610ac461098d565b5060051b60200190565b60006020808385031215610ae157600080fd5b823567ffffffffffffffff811115610af857600080fd5b8301601f81018513610b0957600080fd5b8035610b1c610b1782610aaa565b6109a3565b81815260a09182028301840191848201919088841115610b3b57600080fd5b938501935b83851015610b6157610b5289866109fa565b83529384019391850191610b40565b50979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610b9d57610b9d610b6d565b500290565b634e487b7160e01b600052601260045260246000fd5b600082610bc757610bc7610ba2565b500490565b634e487b7160e01b600052603260045260246000fd5b805161ffff8116811461020057600080fd5b600080600080600080600060e0888a031215610c0f57600080fd5b8751610c1a816109d4565b8097505060208801518060020b8114610c3257600080fd5b9550610c4060408901610be2565b9450610c4e60608901610be2565b9350610c5c60808901610be2565b925060a088015160ff81168114610c7257600080fd5b60c0890151909250610c83816109ec565b8091505092959891949750929550565b600063ffffffff808316818516808303821115610cb257610cb2610b6d565b01949350505050565b6020808252825182820181905260009190848201906040850190845b81811015610cf957835163ffffffff1683529284019291840191600101610cd7565b50909695505050505050565b600082601f830112610d1657600080fd5b81516020610d26610b1783610aaa565b82815260059290921b84018101918181019086841115610d4557600080fd5b8286015b84811015610d69578051610d5c816109d4565b8352918301918301610d49565b509695505050505050565b60008060408385031215610d8757600080fd5b825167ffffffffffffffff80821115610d9f57600080fd5b818501915085601f830112610db357600080fd5b81516020610dc3610b1783610aaa565b82815260059290921b84018101918181019089841115610de257600080fd5b948201945b83861015610e105785518060060b8114610e015760008081fd5b82529482019490820190610de7565b91880151919650909350505080821115610e2957600080fd5b50610e3685828601610d05565b9150509250929050565b60008160060b8360060b6000811281667fffffffffffff1901831281151615610e6b57610e6b610b6d565b81667fffffffffffff018313811615610e8657610e86610b6d565b5090039392505050565b60008160060b8360060b80610ea757610ea7610ba2565b667fffffffffffff19821460001982141615610ec557610ec5610b6d565b90059392505050565b60008219821115610ee157610ee1610b6d565b500190565b600082821015610ef857610ef8610b6d565b500390565b6000600160ff1b821415610f1357610f13610b6d565b5060000390565b60008160020b627fffff19811415610f3457610f34610b6d565b60000392915050565b600082610f4c57610f4c610ba2565b50069056fea2646970667358221220333614865f9c2062975c4fbe320df876c4ad111ba2edcf188c6d17363512481f64736f6c63430008090033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c80631217931b14610045578063caf0f0331461006a575b600080fd5b610058610053366004610a8e565b61007d565b60405190815260200160405180910390f35b610058610078366004610ace565b61011b565b60008061009283600001518460400151610205565b905060006100b6826001600160a01b0316670de0b6b3a7640000600160601b6103fa565b90506000816100cd670de0b6b3a764000080610b83565b6100d79190610bb8565b9050600085602001516100f3576100ee8280610b83565b6100fd565b6100fd8380610b83565b9050610111670de0b6b3a764000082610bb8565b9695505050505050565b60006002825111156101745760405162461bcd60e51b815260206004820152601a60248201527f696e76616c696420706f6f6c20726f75746573206c656e67746800000000000060448201526064015b60405180910390fd5b8151600214156101da5760006101a38360008151811061019657610196610bcc565b602002602001015161007d565b905060006101bd8460018151811061019657610196610bcc565b90506101d28282670de0b6b3a76400006103fa565b949350505050565b815160011415610200576101fa8260008151811061019657610196610bcc565b92915050565b919050565b600063ffffffff821661029257826001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e06040518083038186803b15801561024b57600080fd5b505afa15801561025f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102839190610bf4565b509495506101fa945050505050565b6040805160028082526060820183526000926020830190803683370190505090506102be836001610c93565b816000815181106102d1576102d1610bcc565b602002602001019063ffffffff16908163ffffffff168152505060018160018151811061030057610300610bcc565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0386169063883bdbfd90610344908590600401610cbb565b60006040518083038186803b15801561035c57600080fd5b505afa158015610370573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103989190810190610d74565b5090506103f18460030b826000815181106103b5576103b5610bcc565b6020026020010151836001815181106103d0576103d0610bcc565b60200260200101516103e29190610e40565b6103ec9190610e90565b610576565b95945050505050565b600080806000198587098587029250828110838203039150508060001415610434576000841161042957600080fd5b50829004905061056f565b80841161044057600080fd5b60008486880980840393811190920391905060008561046181196001610ece565b169586900495938490049360008190030460010190506104818184610b83565b909317926000610492876003610b83565b60021890506104a18188610b83565b6104ac906002610ee6565b6104b69082610b83565b90506104c28188610b83565b6104cd906002610ee6565b6104d79082610b83565b90506104e38188610b83565b6104ee906002610ee6565b6104f89082610b83565b90506105048188610b83565b61050f906002610ee6565b6105199082610b83565b90506105258188610b83565b610530906002610ee6565b61053a9082610b83565b90506105468188610b83565b610551906002610ee6565b61055b9082610b83565b90506105678186610b83565b955050505050505b9392505050565b60008060008360020b1261058d578260020b61059a565b8260020b61059a90610efd565b90506105a9620d89e719610f1a565b62ffffff168111156105e15760405162461bcd60e51b81526020600482015260016024820152601560fa1b604482015260640161016b565b6000600182166105f557600160801b610607565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff1690506002821615610646576080610641826ffff97272373d413259a46990580e213a610b83565b901c90505b600482161561067057608061066b826ffff2e50f5f656932ef12357cf3c7fdcc610b83565b901c90505b600882161561069a576080610695826fffe5caca7e10e4e61c3624eaa0941cd0610b83565b901c90505b60108216156106c45760806106bf826fffcb9843d60f6159c9db58835c926644610b83565b901c90505b60208216156106ee5760806106e9826fff973b41fa98c081472e6896dfb254c0610b83565b901c90505b6040821615610718576080610713826fff2ea16466c96a3843ec78b326b52861610b83565b901c90505b608082161561074257608061073d826ffe5dee046a99a2a811c461f1969c3053610b83565b901c90505b61010082161561076d576080610768826ffcbe86c7900a88aedcffc83b479aa3a4610b83565b901c90505b610200821615610798576080610793826ff987a7253ac413176f2b074cf7815e54610b83565b901c90505b6104008216156107c35760806107be826ff3392b0822b70005940c7a398e4b70f3610b83565b901c90505b6108008216156107ee5760806107e9826fe7159475a2c29b7443b29c7fa6e889d9610b83565b901c90505b611000821615610819576080610814826fd097f3bdfd2022b8845ad8f792aa5825610b83565b901c90505b61200082161561084457608061083f826fa9f746462d870fdf8a65dc1f90e061e5610b83565b901c90505b61400082161561086f57608061086a826f70d869a156d2a1b890bb3df62baf32f7610b83565b901c90505b61800082161561089a576080610895826f31be135f97d08fd981231505542fcfa6610b83565b901c90505b620100008216156108c65760806108c1826f09aa508b5b7a84e1c677de54f3e99bc9610b83565b901c90505b620200008216156108f15760806108ec826e5d6af8dedb81196699c329225ee604610b83565b901c90505b6204000082161561091b576080610916826d2216e584f5fa1ea926041bedfe98610b83565b901c90505b6208000082161561094357608061093e826b048a170391f7dc42444e8fa2610b83565b901c90505b60008460020b131561095e5761095b81600019610bb8565b90505b61096d64010000000082610f3d565b1561097957600161097c565b60005b6101d29060ff16602083901c610ece565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156109cc576109cc61098d565b604052919050565b6001600160a01b03811681146109e957600080fd5b50565b80151581146109e957600080fd5b600060a08284031215610a0c57600080fd5b60405160a0810181811067ffffffffffffffff82111715610a2f57610a2f61098d565b6040529050808235610a40816109d4565b81526020830135610a50816109ec565b6020820152604083013563ffffffff81168114610a6c57600080fd5b8060408301525060608301356060820152608083013560808201525092915050565b600060a08284031215610aa057600080fd5b61056f83836109fa565b600067ffffffffffffffff821115610ac457610ac461098d565b5060051b60200190565b60006020808385031215610ae157600080fd5b823567ffffffffffffffff811115610af857600080fd5b8301601f81018513610b0957600080fd5b8035610b1c610b1782610aaa565b6109a3565b81815260a09182028301840191848201919088841115610b3b57600080fd5b938501935b83851015610b6157610b5289866109fa565b83529384019391850191610b40565b50979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615610b9d57610b9d610b6d565b500290565b634e487b7160e01b600052601260045260246000fd5b600082610bc757610bc7610ba2565b500490565b634e487b7160e01b600052603260045260246000fd5b805161ffff8116811461020057600080fd5b600080600080600080600060e0888a031215610c0f57600080fd5b8751610c1a816109d4565b8097505060208801518060020b8114610c3257600080fd5b9550610c4060408901610be2565b9450610c4e60608901610be2565b9350610c5c60808901610be2565b925060a088015160ff81168114610c7257600080fd5b60c0890151909250610c83816109ec565b8091505092959891949750929550565b600063ffffffff808316818516808303821115610cb257610cb2610b6d565b01949350505050565b6020808252825182820181905260009190848201906040850190845b81811015610cf957835163ffffffff1683529284019291840191600101610cd7565b50909695505050505050565b600082601f830112610d1657600080fd5b81516020610d26610b1783610aaa565b82815260059290921b84018101918181019086841115610d4557600080fd5b8286015b84811015610d69578051610d5c816109d4565b8352918301918301610d49565b509695505050505050565b60008060408385031215610d8757600080fd5b825167ffffffffffffffff80821115610d9f57600080fd5b818501915085601f830112610db357600080fd5b81516020610dc3610b1783610aaa565b82815260059290921b84018101918181019089841115610de257600080fd5b948201945b83861015610e105785518060060b8114610e015760008081fd5b82529482019490820190610de7565b91880151919650909350505080821115610e2957600080fd5b50610e3685828601610d05565b9150509250929050565b60008160060b8360060b6000811281667fffffffffffff1901831281151615610e6b57610e6b610b6d565b81667fffffffffffff018313811615610e8657610e86610b6d565b5090039392505050565b60008160060b8360060b80610ea757610ea7610ba2565b667fffffffffffff19821460001982141615610ec557610ec5610b6d565b90059392505050565b60008219821115610ee157610ee1610b6d565b500190565b600082821015610ef857610ef8610b6d565b500390565b6000600160ff1b821415610f1357610f13610b6d565b5060000390565b60008160020b627fffff19811415610f3457610f34610b6d565b60000392915050565b600082610f4c57610f4c610ba2565b50069056fea2646970667358221220333614865f9c2062975c4fbe320df876c4ad111ba2edcf188c6d17363512481f64736f6c63430008090033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/packages/contracts/deployments/polygon/V2Calculations.json b/packages/contracts/deployments/polygon/V2Calculations.json index 3cbe896aa..fd8280471 100644 --- a/packages/contracts/deployments/polygon/V2Calculations.json +++ b/packages/contracts/deployments/polygon/V2Calculations.json @@ -1,5 +1,5 @@ { - "address": "0xAd0fD5947877382E493e17Fb37303D94c4A1deEF", + "address": "0xe2e3ced160D063C44aD0c75564be83625A7DF456", "abi": [ { "inputs": [ @@ -85,44 +85,44 @@ "type": "function" } ], - "transactionHash": "0x102e87813d60bf992e49fc28b44888df5062ce6be7ce8e49a383a40a32fcf9f7", + "transactionHash": "0x1af7b50e989150a34a5325428ce4e87353d0e6e7dbcf2125fbe55c1f259b5843", "receipt": { "to": null, "from": "0xD9B023522CeCe02251d877bb0EB4f06fDe6F98E6", - "contractAddress": "0xAd0fD5947877382E493e17Fb37303D94c4A1deEF", + "contractAddress": "0xe2e3ced160D063C44aD0c75564be83625A7DF456", "transactionIndex": 0, "gasUsed": "1135180", - "logsBloom": "0x00000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000008000000000000000000008000000000000000000000000040000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000100000000000000000000000000000000040000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000000000000001000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000", - "blockHash": "0x3200870565406dae51192488794d716345465f437a9a357be7dcf81f043834bd", - "transactionHash": "0x102e87813d60bf992e49fc28b44888df5062ce6be7ce8e49a383a40a32fcf9f7", + "logsBloom": "0x00000000000000000002000000000000000000000000000000000000040000000000000000000040000000000000000000008000000000000000000000000000000000000000000000040000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000200000004000000000000000000001000000000000000000000000000000100000000000000000000000000000000000000000000002000000000000000000000000100000", + "blockHash": "0xcf7fa974dfc55c40af9b328cd45f1b08398059f0c5b02333a2e2aa40d882c3e8", + "transactionHash": "0x1af7b50e989150a34a5325428ce4e87353d0e6e7dbcf2125fbe55c1f259b5843", "logs": [ { "transactionIndex": 0, - "blockNumber": 61388013, - "transactionHash": "0x102e87813d60bf992e49fc28b44888df5062ce6be7ce8e49a383a40a32fcf9f7", + "blockNumber": 63042980, + "transactionHash": "0x1af7b50e989150a34a5325428ce4e87353d0e6e7dbcf2125fbe55c1f259b5843", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x000000000000000000000000d9b023522cece02251d877bb0eb4f06fde6f98e6", - "0x00000000000000000000000000856730088a5c3191bd26eb482e45229555ce57" + "0x000000000000000000000000ef46d5fe753c988606e6f703260d816af53b03eb" ], - "data": "0x00000000000000000000000000000000000000000000000005838a1183e2b4480000000000000000000000000000000000000000000000022c9551244e000d980000000000000000000000000000000000000000000004f2cbe8b4425230b3700000000000000000000000000000000000000000000000022711c712ca1d59500000000000000000000000000000000000000000000004f2d16c3e53d61367b8", + "data": "0x00000000000000000000000000000000000000000000000005838a1183e2b4480000000000000000000000000000000000000000000000012e89127a282cc3c200000000000000000000000000000000000000000000003a757ea7454ac73a0e00000000000000000000000000000000000000000000000129058868a44a0f7a00000000000000000000000000000000000000000000003a7b023156cea9ee56", "logIndex": 0, - "blockHash": "0x3200870565406dae51192488794d716345465f437a9a357be7dcf81f043834bd" + "blockHash": "0xcf7fa974dfc55c40af9b328cd45f1b08398059f0c5b02333a2e2aa40d882c3e8" } ], - "blockNumber": 61388013, + "blockNumber": 63042980, "cumulativeGasUsed": "1135180", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 6, - "solcInputHash": "fda2ec31b4234f11c5d21e351a4ace99", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_acceptedTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_paymentCycle\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_loanDuration\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_lastRepaidTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"enum PaymentCycleType\",\"name\":\"_bidPaymentCycleType\",\"type\":\"PaymentCycleType\"}],\"name\":\"calculateNextDueDate\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"dueDate_\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum PaymentType\",\"name\":\"_type\",\"type\":\"PaymentType\"},{\"internalType\":\"enum PaymentCycleType\",\"name\":\"_cycleType\",\"type\":\"PaymentCycleType\"},{\"internalType\":\"uint256\",\"name\":\"_principal\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_duration\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_paymentCycle\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_apr\",\"type\":\"uint16\"}],\"name\":\"calculatePaymentCycleAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateAmountOwed(Bid storage,uint256,PaymentCycleType,uint32)\":{\"params\":{\"_bid\":\"The loan bid struct to get the owed amount for.\",\"_paymentCycleType\":\"The payment cycle type of the loan (Seconds or Monthly).\",\"_timestamp\":\"The timestamp at which to get the owed amount at.\"}},\"calculatePaymentCycleAmount(PaymentType,PaymentCycleType,uint256,uint32,uint32,uint16)\":{\"params\":{\"_apr\":\"The annual percentage rate of the loan.\",\"_cycleType\":\"The cycle type set for the loan. (Seconds or Monthly)\",\"_duration\":\"The length of the loan.\",\"_paymentCycle\":\"The length of the loan's payment cycle.\",\"_principal\":\"The starting amount that is owed on the loan.\",\"_type\":\"The payment type of the loan.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateAmountOwed(Bid storage,uint256,PaymentCycleType,uint32)\":{\"notice\":\"Calculates the amount owed for a loan.\"},\"calculatePaymentCycleAmount(PaymentType,PaymentCycleType,uint256,uint32,uint32,uint16)\":{\"notice\":\"Calculates the amount owed for a loan for the next payment cycle.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/V2Calculations.sol\":\"V2Calculations\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\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`.\\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 /**\\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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\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 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 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 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\",\"keccak256\":\"0x2c0b89cef83f353c6f9488c013d8a5968587ffdd6dfc26aad53774214b97e229\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.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 IERC165Upgradeable {\\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\":\"0xc6cef87559d0aeffdf0a99803de655938a7779ec0a3cd5d4383483ad85565a09\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (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 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 /**\\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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\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 return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\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\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\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 /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// CAUTION\\n// This version of SafeMath should only be used with Solidity 0.8 or later,\\n// because it relies on the compiler's built in overflow checks.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations.\\n *\\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\\n * now has built in overflow checking.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator.\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0f633a0223d9a1dcccfcf38a64c9de0874dfcbfac0c6941ccf074d63a2ce0e1e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc3ff3f5c4584e1d9a483ad7ced51ab64523201f4e3d3c65293e4ca8aeb77a961\",\"license\":\"MIT\"},\"contracts/EAS/TellerAS.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\nimport \\\"../Types.sol\\\";\\nimport \\\"../interfaces/IEAS.sol\\\";\\nimport \\\"../interfaces/IASRegistry.sol\\\";\\n\\n/**\\n * @title TellerAS - Teller Attestation Service - based on EAS - Ethereum Attestation Service\\n */\\ncontract TellerAS is IEAS {\\n error AccessDenied();\\n error AlreadyRevoked();\\n error InvalidAttestation();\\n error InvalidExpirationTime();\\n error InvalidOffset();\\n error InvalidRegistry();\\n error InvalidSchema();\\n error InvalidVerifier();\\n error NotFound();\\n error NotPayable();\\n\\n string public constant VERSION = \\\"0.8\\\";\\n\\n // A terminator used when concatenating and hashing multiple fields.\\n string private constant HASH_TERMINATOR = \\\"@\\\";\\n\\n // The AS global registry.\\n IASRegistry private immutable _asRegistry;\\n\\n // The EIP712 verifier used to verify signed attestations.\\n IEASEIP712Verifier private immutable _eip712Verifier;\\n\\n // A mapping between attestations and their related attestations.\\n mapping(bytes32 => bytes32[]) private _relatedAttestations;\\n\\n // A mapping between an account and its received attestations.\\n mapping(address => mapping(bytes32 => bytes32[]))\\n private _receivedAttestations;\\n\\n // A mapping between an account and its sent attestations.\\n mapping(address => mapping(bytes32 => bytes32[])) private _sentAttestations;\\n\\n // A mapping between a schema and its attestations.\\n mapping(bytes32 => bytes32[]) private _schemaAttestations;\\n\\n // The global mapping between attestations and their UUIDs.\\n mapping(bytes32 => Attestation) private _db;\\n\\n // The global counter for the total number of attestations.\\n uint256 private _attestationsCount;\\n\\n bytes32 private _lastUUID;\\n\\n /**\\n * @dev Creates a new EAS instance.\\n *\\n * @param registry The address of the global AS registry.\\n * @param verifier The address of the EIP712 verifier.\\n */\\n constructor(IASRegistry registry, IEASEIP712Verifier verifier) {\\n if (address(registry) == address(0x0)) {\\n revert InvalidRegistry();\\n }\\n\\n if (address(verifier) == address(0x0)) {\\n revert InvalidVerifier();\\n }\\n\\n _asRegistry = registry;\\n _eip712Verifier = verifier;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getASRegistry() external view override returns (IASRegistry) {\\n return _asRegistry;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getEIP712Verifier()\\n external\\n view\\n override\\n returns (IEASEIP712Verifier)\\n {\\n return _eip712Verifier;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getAttestationsCount() external view override returns (uint256) {\\n return _attestationsCount;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function attest(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data\\n ) public payable virtual override returns (bytes32) {\\n return\\n _attest(\\n recipient,\\n schema,\\n expirationTime,\\n refUUID,\\n data,\\n msg.sender\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function attestByDelegation(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public payable virtual override returns (bytes32) {\\n _eip712Verifier.attest(\\n recipient,\\n schema,\\n expirationTime,\\n refUUID,\\n data,\\n attester,\\n v,\\n r,\\n s\\n );\\n\\n return\\n _attest(recipient, schema, expirationTime, refUUID, data, attester);\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function revoke(bytes32 uuid) public virtual override {\\n return _revoke(uuid, msg.sender);\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function revokeByDelegation(\\n bytes32 uuid,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override {\\n _eip712Verifier.revoke(uuid, attester, v, r, s);\\n\\n _revoke(uuid, attester);\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getAttestation(bytes32 uuid)\\n external\\n view\\n override\\n returns (Attestation memory)\\n {\\n return _db[uuid];\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function isAttestationValid(bytes32 uuid)\\n public\\n view\\n override\\n returns (bool)\\n {\\n return _db[uuid].uuid != 0;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function isAttestationActive(bytes32 uuid)\\n public\\n view\\n virtual\\n override\\n returns (bool)\\n {\\n return\\n isAttestationValid(uuid) &&\\n _db[uuid].expirationTime >= block.timestamp &&\\n _db[uuid].revocationTime == 0;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getReceivedAttestationUUIDs(\\n address recipient,\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view override returns (bytes32[] memory) {\\n return\\n _sliceUUIDs(\\n _receivedAttestations[recipient][schema],\\n start,\\n length,\\n reverseOrder\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getReceivedAttestationUUIDsCount(address recipient, bytes32 schema)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n return _receivedAttestations[recipient][schema].length;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getSentAttestationUUIDs(\\n address attester,\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view override returns (bytes32[] memory) {\\n return\\n _sliceUUIDs(\\n _sentAttestations[attester][schema],\\n start,\\n length,\\n reverseOrder\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getSentAttestationUUIDsCount(address recipient, bytes32 schema)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n return _sentAttestations[recipient][schema].length;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getRelatedAttestationUUIDs(\\n bytes32 uuid,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view override returns (bytes32[] memory) {\\n return\\n _sliceUUIDs(\\n _relatedAttestations[uuid],\\n start,\\n length,\\n reverseOrder\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getRelatedAttestationUUIDsCount(bytes32 uuid)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n return _relatedAttestations[uuid].length;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getSchemaAttestationUUIDs(\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view override returns (bytes32[] memory) {\\n return\\n _sliceUUIDs(\\n _schemaAttestations[schema],\\n start,\\n length,\\n reverseOrder\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getSchemaAttestationUUIDsCount(bytes32 schema)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n return _schemaAttestations[schema].length;\\n }\\n\\n /**\\n * @dev Attests to a specific AS.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param expirationTime The expiration time of the attestation.\\n * @param refUUID An optional related attestation's UUID.\\n * @param data Additional custom data.\\n * @param attester The attesting account.\\n *\\n * @return The UUID of the new attestation.\\n */\\n function _attest(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data,\\n address attester\\n ) private returns (bytes32) {\\n if (expirationTime <= block.timestamp) {\\n revert InvalidExpirationTime();\\n }\\n\\n IASRegistry.ASRecord memory asRecord = _asRegistry.getAS(schema);\\n if (asRecord.uuid == EMPTY_UUID) {\\n revert InvalidSchema();\\n }\\n\\n IASResolver resolver = asRecord.resolver;\\n if (address(resolver) != address(0x0)) {\\n if (msg.value != 0 && !resolver.isPayable()) {\\n revert NotPayable();\\n }\\n\\n if (\\n !resolver.resolve{ value: msg.value }(\\n recipient,\\n asRecord.schema,\\n data,\\n expirationTime,\\n attester\\n )\\n ) {\\n revert InvalidAttestation();\\n }\\n }\\n\\n Attestation memory attestation = Attestation({\\n uuid: EMPTY_UUID,\\n schema: schema,\\n recipient: recipient,\\n attester: attester,\\n time: block.timestamp,\\n expirationTime: expirationTime,\\n revocationTime: 0,\\n refUUID: refUUID,\\n data: data\\n });\\n\\n _lastUUID = _getUUID(attestation);\\n attestation.uuid = _lastUUID;\\n\\n _receivedAttestations[recipient][schema].push(_lastUUID);\\n _sentAttestations[attester][schema].push(_lastUUID);\\n _schemaAttestations[schema].push(_lastUUID);\\n\\n _db[_lastUUID] = attestation;\\n _attestationsCount++;\\n\\n if (refUUID != 0) {\\n if (!isAttestationValid(refUUID)) {\\n revert NotFound();\\n }\\n\\n _relatedAttestations[refUUID].push(_lastUUID);\\n }\\n\\n emit Attested(recipient, attester, _lastUUID, schema);\\n\\n return _lastUUID;\\n }\\n\\n function getLastUUID() external view returns (bytes32) {\\n return _lastUUID;\\n }\\n\\n /**\\n * @dev Revokes an existing attestation to a specific AS.\\n *\\n * @param uuid The UUID of the attestation to revoke.\\n * @param attester The attesting account.\\n */\\n function _revoke(bytes32 uuid, address attester) private {\\n Attestation storage attestation = _db[uuid];\\n if (attestation.uuid == EMPTY_UUID) {\\n revert NotFound();\\n }\\n\\n if (attestation.attester != attester) {\\n revert AccessDenied();\\n }\\n\\n if (attestation.revocationTime != 0) {\\n revert AlreadyRevoked();\\n }\\n\\n attestation.revocationTime = block.timestamp;\\n\\n emit Revoked(attestation.recipient, attester, uuid, attestation.schema);\\n }\\n\\n /**\\n * @dev Calculates a UUID for a given attestation.\\n *\\n * @param attestation The input attestation.\\n *\\n * @return Attestation UUID.\\n */\\n function _getUUID(Attestation memory attestation)\\n private\\n view\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encodePacked(\\n attestation.schema,\\n attestation.recipient,\\n attestation.attester,\\n attestation.time,\\n attestation.expirationTime,\\n attestation.data,\\n HASH_TERMINATOR,\\n _attestationsCount\\n )\\n );\\n }\\n\\n /**\\n * @dev Returns a slice in an array of attestation UUIDs.\\n *\\n * @param uuids The array of attestation UUIDs.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function _sliceUUIDs(\\n bytes32[] memory uuids,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) private pure returns (bytes32[] memory) {\\n uint256 attestationsLength = uuids.length;\\n if (attestationsLength == 0) {\\n return new bytes32[](0);\\n }\\n\\n if (start >= attestationsLength) {\\n revert InvalidOffset();\\n }\\n\\n uint256 len = length;\\n if (attestationsLength < start + length) {\\n len = attestationsLength - start;\\n }\\n\\n bytes32[] memory res = new bytes32[](len);\\n\\n for (uint256 i = 0; i < len; ++i) {\\n res[i] = uuids[\\n reverseOrder ? attestationsLength - (start + i + 1) : start + i\\n ];\\n }\\n\\n return res;\\n }\\n}\\n\",\"keccak256\":\"0x5a41ca49530d1b4697b5ea58b02900a3297b42a84e49c2753a55b5939c84a415\",\"license\":\"MIT\"},\"contracts/TellerV2Storage.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\nimport { IMarketRegistry } from \\\"./interfaces/IMarketRegistry.sol\\\";\\nimport \\\"./interfaces/IEscrowVault.sol\\\";\\nimport \\\"./interfaces/IReputationManager.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./interfaces/ICollateralManager.sol\\\";\\nimport { PaymentType, PaymentCycleType } from \\\"./libraries/V2Calculations.sol\\\";\\nimport \\\"./interfaces/ILenderManager.sol\\\";\\n\\nenum BidState {\\n NONEXISTENT,\\n PENDING,\\n CANCELLED,\\n ACCEPTED,\\n PAID,\\n LIQUIDATED,\\n CLOSED\\n}\\n\\n/**\\n * @notice Represents a total amount for a payment.\\n * @param principal Amount that counts towards the principal.\\n * @param interest Amount that counts toward interest.\\n */\\nstruct Payment {\\n uint256 principal;\\n uint256 interest;\\n}\\n\\n/**\\n * @notice Details about a loan request.\\n * @param borrower Account address who is requesting a loan.\\n * @param receiver Account address who will receive the loan amount.\\n * @param lender Account address who accepted and funded the loan request.\\n * @param marketplaceId ID of the marketplace the bid was submitted to.\\n * @param metadataURI ID of off chain metadata to find additional information of the loan request.\\n * @param loanDetails Struct of the specific loan details.\\n * @param terms Struct of the loan request terms.\\n * @param state Represents the current state of the loan.\\n */\\nstruct Bid {\\n address borrower;\\n address receiver;\\n address lender; // if this is the LenderManager address, we use that .owner() as source of truth\\n uint256 marketplaceId;\\n bytes32 _metadataURI; // DEPRECATED\\n LoanDetails loanDetails;\\n Terms terms;\\n BidState state;\\n PaymentType paymentType;\\n}\\n\\n/**\\n * @notice Details about the loan.\\n * @param lendingToken The token address for the loan.\\n * @param principal The amount of tokens initially lent out.\\n * @param totalRepaid Payment struct that represents the total principal and interest amount repaid.\\n * @param timestamp Timestamp, in seconds, of when the bid was submitted by the borrower.\\n * @param acceptedTimestamp Timestamp, in seconds, of when the bid was accepted by the lender.\\n * @param lastRepaidTimestamp Timestamp, in seconds, of when the last payment was made\\n * @param loanDuration The duration of the loan.\\n */\\nstruct LoanDetails {\\n IERC20 lendingToken;\\n uint256 principal;\\n Payment totalRepaid;\\n uint32 timestamp;\\n uint32 acceptedTimestamp;\\n uint32 lastRepaidTimestamp;\\n uint32 loanDuration;\\n}\\n\\n/**\\n * @notice Information on the terms of a loan request\\n * @param paymentCycleAmount Value of tokens expected to be repaid every payment cycle.\\n * @param paymentCycle Duration, in seconds, of how often a payment must be made.\\n * @param APR Annual percentage rating to be applied on repayments. (10000 == 100%)\\n */\\nstruct Terms {\\n uint256 paymentCycleAmount;\\n uint32 paymentCycle;\\n uint16 APR;\\n}\\n\\nabstract contract TellerV2Storage_G0 {\\n /** Storage Variables */\\n\\n // Current number of bids.\\n uint256 public bidId;\\n\\n // Mapping of bidId to bid information.\\n mapping(uint256 => Bid) public bids;\\n\\n // Mapping of borrowers to borrower requests.\\n mapping(address => uint256[]) public borrowerBids;\\n\\n // Mapping of volume filled by lenders.\\n mapping(address => uint256) public __lenderVolumeFilled; // DEPRECIATED\\n\\n // Volume filled by all lenders.\\n uint256 public __totalVolumeFilled; // DEPRECIATED\\n\\n // List of allowed lending tokens\\n EnumerableSet.AddressSet internal __lendingTokensSet; // DEPRECATED\\n\\n IMarketRegistry public marketRegistry;\\n IReputationManager public reputationManager;\\n\\n // Mapping of borrowers to borrower requests.\\n mapping(address => EnumerableSet.UintSet) internal _borrowerBidsActive;\\n\\n mapping(uint256 => uint32) public bidDefaultDuration;\\n mapping(uint256 => uint32) public bidExpirationTime;\\n\\n // Mapping of volume filled by lenders.\\n // Asset address => Lender address => Volume amount\\n mapping(address => mapping(address => uint256)) public lenderVolumeFilled;\\n\\n // Volume filled by all lenders.\\n // Asset address => Volume amount\\n mapping(address => uint256) public totalVolumeFilled;\\n\\n uint256 public version;\\n\\n // Mapping of metadataURIs by bidIds.\\n // Bid Id => metadataURI string\\n mapping(uint256 => string) public uris;\\n}\\n\\nabstract contract TellerV2Storage_G1 is TellerV2Storage_G0 {\\n // market ID => trusted forwarder\\n mapping(uint256 => address) internal _trustedMarketForwarders;\\n // trusted forwarder => set of pre-approved senders\\n mapping(address => EnumerableSet.AddressSet)\\n internal _approvedForwarderSenders;\\n}\\n\\nabstract contract TellerV2Storage_G2 is TellerV2Storage_G1 {\\n address public lenderCommitmentForwarder;\\n}\\n\\nabstract contract TellerV2Storage_G3 is TellerV2Storage_G2 {\\n ICollateralManager public collateralManager;\\n}\\n\\nabstract contract TellerV2Storage_G4 is TellerV2Storage_G3 {\\n // Address of the lender manager contract\\n ILenderManager public lenderManager;\\n // BidId to payment cycle type (custom or monthly)\\n mapping(uint256 => PaymentCycleType) public bidPaymentCycleType;\\n}\\n\\nabstract contract TellerV2Storage_G5 is TellerV2Storage_G4 {\\n // Address of the lender manager contract\\n IEscrowVault public escrowVault;\\n}\\n\\nabstract contract TellerV2Storage_G6 is TellerV2Storage_G5 {\\n mapping(uint256 => address) public repaymentListenerForBid;\\n}\\n\\nabstract contract TellerV2Storage_G7 is TellerV2Storage_G6 {\\n mapping(address => bool) public pauserRoleBearer;\\n bool public liquidationsPaused;\\n}\\n\\nabstract contract TellerV2Storage is TellerV2Storage_G7 {}\\n\",\"keccak256\":\"0xe28431a66593cb8d06acf0b95a0f1608abb4e7b2ad37dadedf708d13fd204051\",\"license\":\"MIT\"},\"contracts/Types.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\n// A representation of an empty/uninitialized UUID.\\nbytes32 constant EMPTY_UUID = 0;\\n\",\"keccak256\":\"0x2e4bcf4a965f840193af8729251386c1826cd050411ba4a9e85984a2551fd2ff\",\"license\":\"MIT\"},\"contracts/interfaces/IASRegistry.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\nimport \\\"./IASResolver.sol\\\";\\n\\n/**\\n * @title The global AS registry interface.\\n */\\ninterface IASRegistry {\\n /**\\n * @title A struct representing a record for a submitted AS (Attestation Schema).\\n */\\n struct ASRecord {\\n // A unique identifier of the AS.\\n bytes32 uuid;\\n // Optional schema resolver.\\n IASResolver resolver;\\n // Auto-incrementing index for reference, assigned by the registry itself.\\n uint256 index;\\n // Custom specification of the AS (e.g., an ABI).\\n bytes schema;\\n }\\n\\n /**\\n * @dev Triggered when a new AS has been registered\\n *\\n * @param uuid The AS UUID.\\n * @param index The AS index.\\n * @param schema The AS schema.\\n * @param resolver An optional AS schema resolver.\\n * @param attester The address of the account used to register the AS.\\n */\\n event Registered(\\n bytes32 indexed uuid,\\n uint256 indexed index,\\n bytes schema,\\n IASResolver resolver,\\n address attester\\n );\\n\\n /**\\n * @dev Submits and reserve a new AS\\n *\\n * @param schema The AS data schema.\\n * @param resolver An optional AS schema resolver.\\n *\\n * @return The UUID of the new AS.\\n */\\n function register(bytes calldata schema, IASResolver resolver)\\n external\\n returns (bytes32);\\n\\n /**\\n * @dev Returns an existing AS by UUID\\n *\\n * @param uuid The UUID of the AS to retrieve.\\n *\\n * @return The AS data members.\\n */\\n function getAS(bytes32 uuid) external view returns (ASRecord memory);\\n\\n /**\\n * @dev Returns the global counter for the total number of attestations\\n *\\n * @return The global counter for the total number of attestations.\\n */\\n function getASCount() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x74752921f592df45c8717d7084627e823b1dbc93bad7187cd3023c9690df7e60\",\"license\":\"MIT\"},\"contracts/interfaces/IASResolver.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n\\n// SPDX-License-Identifier: MIT\\n\\n/**\\n * @title The interface of an optional AS resolver.\\n */\\ninterface IASResolver {\\n /**\\n * @dev Returns whether the resolver supports ETH transfers\\n */\\n function isPayable() external pure returns (bool);\\n\\n /**\\n * @dev Resolves an attestation and verifier whether its data conforms to the spec.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The AS data schema.\\n * @param data The actual attestation data.\\n * @param expirationTime The expiration time of the attestation.\\n * @param msgSender The sender of the original attestation message.\\n *\\n * @return Whether the data is valid according to the scheme.\\n */\\n function resolve(\\n address recipient,\\n bytes calldata schema,\\n bytes calldata data,\\n uint256 expirationTime,\\n address msgSender\\n ) external payable returns (bool);\\n}\\n\",\"keccak256\":\"0xfce671ea099d9f997a69c3447eb4a9c9693d37c5b97e43ada376e614e1c7cb61\",\"license\":\"MIT\"},\"contracts/interfaces/ICollateralManager.sol\":{\"content\":\"// SPDX-Licence-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\n\\nimport { Collateral } from \\\"./escrow/ICollateralEscrowV1.sol\\\";\\n\\ninterface ICollateralManager {\\n /**\\n * @notice Checks the validity of a borrower's collateral balance.\\n * @param _bidId The id of the associated bid.\\n * @param _collateralInfo Additional information about the collateral asset.\\n * @return validation_ Boolean indicating if the collateral balance was validated.\\n */\\n function commitCollateral(\\n uint256 _bidId,\\n Collateral[] calldata _collateralInfo\\n ) external returns (bool validation_);\\n\\n /**\\n * @notice Checks the validity of a borrower's collateral balance and commits it to a bid.\\n * @param _bidId The id of the associated bid.\\n * @param _collateralInfo Additional information about the collateral asset.\\n * @return validation_ Boolean indicating if the collateral balance was validated.\\n */\\n function commitCollateral(\\n uint256 _bidId,\\n Collateral calldata _collateralInfo\\n ) external returns (bool validation_);\\n\\n function checkBalances(\\n address _borrowerAddress,\\n Collateral[] calldata _collateralInfo\\n ) external returns (bool validated_, bool[] memory checks_);\\n\\n /**\\n * @notice Deploys a new collateral escrow.\\n * @param _bidId The associated bidId of the collateral escrow.\\n */\\n function deployAndDeposit(uint256 _bidId) external;\\n\\n /**\\n * @notice Gets the address of a deployed escrow.\\n * @notice _bidId The bidId to return the escrow for.\\n * @return The address of the escrow.\\n */\\n function getEscrow(uint256 _bidId) external view returns (address);\\n\\n /**\\n * @notice Gets the collateral info for a given bid id.\\n * @param _bidId The bidId to return the collateral info for.\\n * @return The stored collateral info.\\n */\\n function getCollateralInfo(uint256 _bidId)\\n external\\n view\\n returns (Collateral[] memory);\\n\\n function getCollateralAmount(uint256 _bidId, address collateralAssetAddress)\\n external\\n view\\n returns (uint256 _amount);\\n\\n /**\\n * @notice Withdraws deposited collateral from the created escrow of a bid.\\n * @param _bidId The id of the bid to withdraw collateral for.\\n */\\n function withdraw(uint256 _bidId) external;\\n\\n /**\\n * @notice Re-checks the validity of a borrower's collateral balance committed to a bid.\\n * @param _bidId The id of the associated bid.\\n * @return validation_ Boolean indicating if the collateral balance was validated.\\n */\\n function revalidateCollateral(uint256 _bidId) external returns (bool);\\n\\n /**\\n * @notice Sends the deposited collateral to a lender of a bid.\\n * @notice Can only be called by the protocol.\\n * @param _bidId The id of the liquidated bid.\\n */\\n function lenderClaimCollateral(uint256 _bidId) external;\\n\\n\\n\\n /**\\n * @notice Sends the deposited collateral to a lender of a bid.\\n * @notice Can only be called by the protocol.\\n * @param _bidId The id of the liquidated bid.\\n * @param _collateralRecipient the address that will receive the collateral \\n */\\n function lenderClaimCollateralWithRecipient(uint256 _bidId, address _collateralRecipient) external;\\n\\n\\n /**\\n * @notice Sends the deposited collateral to a liquidator of a bid.\\n * @notice Can only be called by the protocol.\\n * @param _bidId The id of the liquidated bid.\\n * @param _liquidatorAddress The address of the liquidator to send the collateral to.\\n */\\n function liquidateCollateral(uint256 _bidId, address _liquidatorAddress)\\n external;\\n}\\n\",\"keccak256\":\"0x58734812c9549a2d53d86ac6349b2fba615460732145e863ef9d0c8dc3712d08\"},\"contracts/interfaces/IEAS.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\nimport \\\"./IASRegistry.sol\\\";\\nimport \\\"./IEASEIP712Verifier.sol\\\";\\n\\n/**\\n * @title EAS - Ethereum Attestation Service interface\\n */\\ninterface IEAS {\\n /**\\n * @dev A struct representing a single attestation.\\n */\\n struct Attestation {\\n // A unique identifier of the attestation.\\n bytes32 uuid;\\n // A unique identifier of the AS.\\n bytes32 schema;\\n // The recipient of the attestation.\\n address recipient;\\n // The attester/sender of the attestation.\\n address attester;\\n // The time when the attestation was created (Unix timestamp).\\n uint256 time;\\n // The time when the attestation expires (Unix timestamp).\\n uint256 expirationTime;\\n // The time when the attestation was revoked (Unix timestamp).\\n uint256 revocationTime;\\n // The UUID of the related attestation.\\n bytes32 refUUID;\\n // Custom attestation data.\\n bytes data;\\n }\\n\\n /**\\n * @dev Triggered when an attestation has been made.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param attester The attesting account.\\n * @param uuid The UUID the revoked attestation.\\n * @param schema The UUID of the AS.\\n */\\n event Attested(\\n address indexed recipient,\\n address indexed attester,\\n bytes32 uuid,\\n bytes32 indexed schema\\n );\\n\\n /**\\n * @dev Triggered when an attestation has been revoked.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param attester The attesting account.\\n * @param schema The UUID of the AS.\\n * @param uuid The UUID the revoked attestation.\\n */\\n event Revoked(\\n address indexed recipient,\\n address indexed attester,\\n bytes32 uuid,\\n bytes32 indexed schema\\n );\\n\\n /**\\n * @dev Returns the address of the AS global registry.\\n *\\n * @return The address of the AS global registry.\\n */\\n function getASRegistry() external view returns (IASRegistry);\\n\\n /**\\n * @dev Returns the address of the EIP712 verifier used to verify signed attestations.\\n *\\n * @return The address of the EIP712 verifier used to verify signed attestations.\\n */\\n function getEIP712Verifier() external view returns (IEASEIP712Verifier);\\n\\n /**\\n * @dev Returns the global counter for the total number of attestations.\\n *\\n * @return The global counter for the total number of attestations.\\n */\\n function getAttestationsCount() external view returns (uint256);\\n\\n /**\\n * @dev Attests to a specific AS.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param expirationTime The expiration time of the attestation.\\n * @param refUUID An optional related attestation's UUID.\\n * @param data Additional custom data.\\n *\\n * @return The UUID of the new attestation.\\n */\\n function attest(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data\\n ) external payable returns (bytes32);\\n\\n /**\\n * @dev Attests to a specific AS using a provided EIP712 signature.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param expirationTime The expiration time of the attestation.\\n * @param refUUID An optional related attestation's UUID.\\n * @param data Additional custom data.\\n * @param attester The attesting account.\\n * @param v The recovery ID.\\n * @param r The x-coordinate of the nonce R.\\n * @param s The signature data.\\n *\\n * @return The UUID of the new attestation.\\n */\\n function attestByDelegation(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external payable returns (bytes32);\\n\\n /**\\n * @dev Revokes an existing attestation to a specific AS.\\n *\\n * @param uuid The UUID of the attestation to revoke.\\n */\\n function revoke(bytes32 uuid) external;\\n\\n /**\\n * @dev Attests to a specific AS using a provided EIP712 signature.\\n *\\n * @param uuid The UUID of the attestation to revoke.\\n * @param attester The attesting account.\\n * @param v The recovery ID.\\n * @param r The x-coordinate of the nonce R.\\n * @param s The signature data.\\n */\\n function revokeByDelegation(\\n bytes32 uuid,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns an existing attestation by UUID.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n *\\n * @return The attestation data members.\\n */\\n function getAttestation(bytes32 uuid)\\n external\\n view\\n returns (Attestation memory);\\n\\n /**\\n * @dev Checks whether an attestation exists.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n *\\n * @return Whether an attestation exists.\\n */\\n function isAttestationValid(bytes32 uuid) external view returns (bool);\\n\\n /**\\n * @dev Checks whether an attestation is active.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n *\\n * @return Whether an attestation is active.\\n */\\n function isAttestationActive(bytes32 uuid) external view returns (bool);\\n\\n /**\\n * @dev Returns all received attestation UUIDs.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function getReceivedAttestationUUIDs(\\n address recipient,\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view returns (bytes32[] memory);\\n\\n /**\\n * @dev Returns the number of received attestation UUIDs.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n *\\n * @return The number of attestations.\\n */\\n function getReceivedAttestationUUIDsCount(address recipient, bytes32 schema)\\n external\\n view\\n returns (uint256);\\n\\n /**\\n * @dev Returns all sent attestation UUIDs.\\n *\\n * @param attester The attesting account.\\n * @param schema The UUID of the AS.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function getSentAttestationUUIDs(\\n address attester,\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view returns (bytes32[] memory);\\n\\n /**\\n * @dev Returns the number of sent attestation UUIDs.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n *\\n * @return The number of attestations.\\n */\\n function getSentAttestationUUIDsCount(address recipient, bytes32 schema)\\n external\\n view\\n returns (uint256);\\n\\n /**\\n * @dev Returns all attestations related to a specific attestation.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function getRelatedAttestationUUIDs(\\n bytes32 uuid,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view returns (bytes32[] memory);\\n\\n /**\\n * @dev Returns the number of related attestation UUIDs.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n *\\n * @return The number of related attestations.\\n */\\n function getRelatedAttestationUUIDsCount(bytes32 uuid)\\n external\\n view\\n returns (uint256);\\n\\n /**\\n * @dev Returns all per-schema attestation UUIDs.\\n *\\n * @param schema The UUID of the AS.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function getSchemaAttestationUUIDs(\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view returns (bytes32[] memory);\\n\\n /**\\n * @dev Returns the number of per-schema attestation UUIDs.\\n *\\n * @param schema The UUID of the AS.\\n *\\n * @return The number of attestations.\\n */\\n function getSchemaAttestationUUIDsCount(bytes32 schema)\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x5db90829269f806ed14a6c638f38d4aac1fa0f85829b34a2fcddd5200261c148\",\"license\":\"MIT\"},\"contracts/interfaces/IEASEIP712Verifier.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n\\n// SPDX-License-Identifier: MIT\\n\\n/**\\n * @title EIP712 typed signatures verifier for EAS delegated attestations interface.\\n */\\ninterface IEASEIP712Verifier {\\n /**\\n * @dev Returns the current nonce per-account.\\n *\\n * @param account The requested accunt.\\n *\\n * @return The current nonce.\\n */\\n function getNonce(address account) external view returns (uint256);\\n\\n /**\\n * @dev Verifies signed attestation.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param expirationTime The expiration time of the attestation.\\n * @param refUUID An optional related attestation's UUID.\\n * @param data Additional custom data.\\n * @param attester The attesting account.\\n * @param v The recovery ID.\\n * @param r The x-coordinate of the nonce R.\\n * @param s The signature data.\\n */\\n function attest(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Verifies signed revocations.\\n *\\n * @param uuid The UUID of the attestation to revoke.\\n * @param attester The attesting account.\\n * @param v The recovery ID.\\n * @param r The x-coordinate of the nonce R.\\n * @param s The signature data.\\n */\\n function revoke(\\n bytes32 uuid,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0xeca3ac3bacec52af15b2c86c5bf1a1be315aade51fa86f95da2b426b28486b1e\",\"license\":\"MIT\"},\"contracts/interfaces/IEscrowVault.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\n\\ninterface IEscrowVault {\\n /**\\n * @notice Deposit tokens on behalf of another account\\n * @param account The address of the account\\n * @param token The address of the token\\n * @param amount The amount to increase the balance\\n */\\n function deposit(address account, address token, uint256 amount) external;\\n\\n function withdraw(address token, uint256 amount) external ;\\n}\\n\",\"keccak256\":\"0x7d80ce49d143f2f509e1992ed41200e07376bea48950e3674db71a343882f2c8\",\"license\":\"MIT\"},\"contracts/interfaces/ILenderManager.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n\\n// SPDX-License-Identifier: MIT\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\\\";\\n\\nabstract contract ILenderManager is IERC721Upgradeable {\\n /**\\n * @notice Registers a new active lender for a loan, minting the nft.\\n * @param _bidId The id for the loan to set.\\n * @param _newLender The address of the new active lender.\\n */\\n function registerLoan(uint256 _bidId, address _newLender) external virtual;\\n}\\n\",\"keccak256\":\"0xceb1ea2ef4c6e2ad7986db84de49c959e8d59844563d27daca5b8d78b732a8f7\",\"license\":\"MIT\"},\"contracts/interfaces/IMarketRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"../EAS/TellerAS.sol\\\";\\nimport { PaymentType, PaymentCycleType } from \\\"../libraries/V2Calculations.sol\\\";\\n\\ninterface IMarketRegistry {\\n function initialize(TellerAS tellerAs) external;\\n\\n function isVerifiedLender(uint256 _marketId, address _lender)\\n external\\n view\\n returns (bool, bytes32);\\n\\n function isMarketOpen(uint256 _marketId) external view returns (bool);\\n\\n function isMarketClosed(uint256 _marketId) external view returns (bool);\\n\\n function isVerifiedBorrower(uint256 _marketId, address _borrower)\\n external\\n view\\n returns (bool, bytes32);\\n\\n function getMarketOwner(uint256 _marketId) external view returns (address);\\n\\n function getMarketFeeRecipient(uint256 _marketId)\\n external\\n view\\n returns (address);\\n\\n function getMarketURI(uint256 _marketId)\\n external\\n view\\n returns (string memory);\\n\\n function getPaymentCycle(uint256 _marketId)\\n external\\n view\\n returns (uint32, PaymentCycleType);\\n\\n function getPaymentDefaultDuration(uint256 _marketId)\\n external\\n view\\n returns (uint32);\\n\\n function getBidExpirationTime(uint256 _marketId)\\n external\\n view\\n returns (uint32);\\n\\n function getMarketplaceFee(uint256 _marketId)\\n external\\n view\\n returns (uint16);\\n\\n function getPaymentType(uint256 _marketId)\\n external\\n view\\n returns (PaymentType);\\n\\n function createMarket(\\n address _initialOwner,\\n uint32 _paymentCycleDuration,\\n uint32 _paymentDefaultDuration,\\n uint32 _bidExpirationTime,\\n uint16 _feePercent,\\n bool _requireLenderAttestation,\\n bool _requireBorrowerAttestation,\\n PaymentType _paymentType,\\n PaymentCycleType _paymentCycleType,\\n string calldata _uri\\n ) external returns (uint256 marketId_);\\n\\n function createMarket(\\n address _initialOwner,\\n uint32 _paymentCycleDuration,\\n uint32 _paymentDefaultDuration,\\n uint32 _bidExpirationTime,\\n uint16 _feePercent,\\n bool _requireLenderAttestation,\\n bool _requireBorrowerAttestation,\\n string calldata _uri\\n ) external returns (uint256 marketId_);\\n\\n function closeMarket(uint256 _marketId) external;\\n}\\n\",\"keccak256\":\"0x2a17561a47cb3517f2820d68d9bbcd86dcd21c59cad7208581004ecd91d5478a\",\"license\":\"MIT\"},\"contracts/interfaces/IReputationManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum RepMark {\\n Good,\\n Delinquent,\\n Default\\n}\\n\\ninterface IReputationManager {\\n function initialize(address protocolAddress) external;\\n\\n function getDelinquentLoanIds(address _account)\\n external\\n returns (uint256[] memory);\\n\\n function getDefaultedLoanIds(address _account)\\n external\\n returns (uint256[] memory);\\n\\n function getCurrentDelinquentLoanIds(address _account)\\n external\\n returns (uint256[] memory);\\n\\n function getCurrentDefaultLoanIds(address _account)\\n external\\n returns (uint256[] memory);\\n\\n function updateAccountReputation(address _account) external;\\n\\n function updateAccountReputation(address _account, uint256 _bidId)\\n external\\n returns (RepMark);\\n}\\n\",\"keccak256\":\"0x8d6e50fd460912231e53135b4459aa2f6f16007ae8deb32bc2cee1e88311a8d8\",\"license\":\"MIT\"},\"contracts/interfaces/escrow/ICollateralEscrowV1.sol\":{\"content\":\"// SPDX-Licence-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\n\\nenum CollateralType {\\n ERC20,\\n ERC721,\\n ERC1155\\n}\\n\\nstruct Collateral {\\n CollateralType _collateralType;\\n uint256 _amount;\\n uint256 _tokenId;\\n address _collateralAddress;\\n}\\n\\ninterface ICollateralEscrowV1 {\\n /**\\n * @notice Deposits a collateral asset into the escrow.\\n * @param _collateralType The type of collateral asset to deposit (ERC721, ERC1155).\\n * @param _collateralAddress The address of the collateral token.i feel\\n * @param _amount The amount to deposit.\\n */\\n function depositAsset(\\n CollateralType _collateralType,\\n address _collateralAddress,\\n uint256 _amount,\\n uint256 _tokenId\\n ) external payable;\\n\\n /**\\n * @notice Withdraws a collateral asset from the escrow.\\n * @param _collateralAddress The address of the collateral contract.\\n * @param _amount The amount to withdraw.\\n * @param _recipient The address to send the assets to.\\n */\\n function withdraw(\\n address _collateralAddress,\\n uint256 _amount,\\n address _recipient\\n ) external;\\n\\n function withdrawDustTokens( \\n address _tokenAddress, \\n uint256 _amount,\\n address _recipient\\n ) external;\\n\\n\\n function getBid() external view returns (uint256);\\n\\n function initialize(uint256 _bidId) external;\\n\\n\\n}\\n\",\"keccak256\":\"0xc5b554eea7e17e47acc632cab40894bac2d2699864fdccc61e08fa8f546c0437\"},\"contracts/libraries/DateTimeLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.6.0 <0.9.0;\\n\\n// ----------------------------------------------------------------------------\\n// BokkyPooBah's DateTime Library v1.01\\n//\\n// A gas-efficient Solidity date and time library\\n//\\n// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\\n//\\n// Tested date range 1970/01/01 to 2345/12/31\\n//\\n// Conventions:\\n// Unit | Range | Notes\\n// :-------- |:-------------:|:-----\\n// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC\\n// year | 1970 ... 2345 |\\n// month | 1 ... 12 |\\n// day | 1 ... 31 |\\n// hour | 0 ... 23 |\\n// minute | 0 ... 59 |\\n// second | 0 ... 59 |\\n// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday\\n//\\n//\\n// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.\\n// ----------------------------------------------------------------------------\\n\\nlibrary BokkyPooBahsDateTimeLibrary {\\n uint constant SECONDS_PER_DAY = 24 * 60 * 60;\\n uint constant SECONDS_PER_HOUR = 60 * 60;\\n uint constant SECONDS_PER_MINUTE = 60;\\n int constant OFFSET19700101 = 2440588;\\n\\n uint constant DOW_MON = 1;\\n uint constant DOW_TUE = 2;\\n uint constant DOW_WED = 3;\\n uint constant DOW_THU = 4;\\n uint constant DOW_FRI = 5;\\n uint constant DOW_SAT = 6;\\n uint constant DOW_SUN = 7;\\n\\n // ------------------------------------------------------------------------\\n // Calculate the number of days from 1970/01/01 to year/month/day using\\n // the date conversion algorithm from\\n // https://aa.usno.navy.mil/faq/JD_formula.html\\n // and subtracting the offset 2440588 so that 1970/01/01 is day 0\\n //\\n // days = day\\n // - 32075\\n // + 1461 * (year + 4800 + (month - 14) / 12) / 4\\n // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12\\n // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4\\n // - offset\\n // ------------------------------------------------------------------------\\n function _daysFromDate(uint year, uint month, uint day)\\n internal\\n pure\\n returns (uint _days)\\n {\\n require(year >= 1970);\\n int _year = int(year);\\n int _month = int(month);\\n int _day = int(day);\\n\\n int __days = _day -\\n 32075 +\\n (1461 * (_year + 4800 + (_month - 14) / 12)) /\\n 4 +\\n (367 * (_month - 2 - ((_month - 14) / 12) * 12)) /\\n 12 -\\n (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /\\n 4 -\\n OFFSET19700101;\\n\\n _days = uint(__days);\\n }\\n\\n // ------------------------------------------------------------------------\\n // Calculate year/month/day from the number of days since 1970/01/01 using\\n // the date conversion algorithm from\\n // http://aa.usno.navy.mil/faq/docs/JD_Formula.php\\n // and adding the offset 2440588 so that 1970/01/01 is day 0\\n //\\n // int L = days + 68569 + offset\\n // int N = 4 * L / 146097\\n // L = L - (146097 * N + 3) / 4\\n // year = 4000 * (L + 1) / 1461001\\n // L = L - 1461 * year / 4 + 31\\n // month = 80 * L / 2447\\n // dd = L - 2447 * month / 80\\n // L = month / 11\\n // month = month + 2 - 12 * L\\n // year = 100 * (N - 49) + year + L\\n // ------------------------------------------------------------------------\\n function _daysToDate(uint _days)\\n internal\\n pure\\n returns (uint year, uint month, uint day)\\n {\\n int __days = int(_days);\\n\\n int L = __days + 68569 + OFFSET19700101;\\n int N = (4 * L) / 146097;\\n L = L - (146097 * N + 3) / 4;\\n int _year = (4000 * (L + 1)) / 1461001;\\n L = L - (1461 * _year) / 4 + 31;\\n int _month = (80 * L) / 2447;\\n int _day = L - (2447 * _month) / 80;\\n L = _month / 11;\\n _month = _month + 2 - 12 * L;\\n _year = 100 * (N - 49) + _year + L;\\n\\n year = uint(_year);\\n month = uint(_month);\\n day = uint(_day);\\n }\\n\\n function timestampFromDate(uint year, uint month, uint day)\\n internal\\n pure\\n returns (uint timestamp)\\n {\\n timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;\\n }\\n\\n function timestampFromDateTime(\\n uint year,\\n uint month,\\n uint day,\\n uint hour,\\n uint minute,\\n uint second\\n ) internal pure returns (uint timestamp) {\\n timestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n hour *\\n SECONDS_PER_HOUR +\\n minute *\\n SECONDS_PER_MINUTE +\\n second;\\n }\\n\\n function timestampToDate(uint timestamp)\\n internal\\n pure\\n returns (uint year, uint month, uint day)\\n {\\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n }\\n\\n function timestampToDateTime(uint timestamp)\\n internal\\n pure\\n returns (\\n uint year,\\n uint month,\\n uint day,\\n uint hour,\\n uint minute,\\n uint second\\n )\\n {\\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n uint secs = timestamp % SECONDS_PER_DAY;\\n hour = secs / SECONDS_PER_HOUR;\\n secs = secs % SECONDS_PER_HOUR;\\n minute = secs / SECONDS_PER_MINUTE;\\n second = secs % SECONDS_PER_MINUTE;\\n }\\n\\n function isValidDate(uint year, uint month, uint day)\\n internal\\n pure\\n returns (bool valid)\\n {\\n if (year >= 1970 && month > 0 && month <= 12) {\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > 0 && day <= daysInMonth) {\\n valid = true;\\n }\\n }\\n }\\n\\n function isValidDateTime(\\n uint year,\\n uint month,\\n uint day,\\n uint hour,\\n uint minute,\\n uint second\\n ) internal pure returns (bool valid) {\\n if (isValidDate(year, month, day)) {\\n if (hour < 24 && minute < 60 && second < 60) {\\n valid = true;\\n }\\n }\\n }\\n\\n function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {\\n (uint year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n leapYear = _isLeapYear(year);\\n }\\n\\n function _isLeapYear(uint year) internal pure returns (bool leapYear) {\\n leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);\\n }\\n\\n function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {\\n weekDay = getDayOfWeek(timestamp) <= DOW_FRI;\\n }\\n\\n function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {\\n weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;\\n }\\n\\n function getDaysInMonth(uint timestamp)\\n internal\\n pure\\n returns (uint daysInMonth)\\n {\\n (uint year, uint month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n daysInMonth = _getDaysInMonth(year, month);\\n }\\n\\n function _getDaysInMonth(uint year, uint month)\\n internal\\n pure\\n returns (uint daysInMonth)\\n {\\n if (\\n month == 1 ||\\n month == 3 ||\\n month == 5 ||\\n month == 7 ||\\n month == 8 ||\\n month == 10 ||\\n month == 12\\n ) {\\n daysInMonth = 31;\\n } else if (month != 2) {\\n daysInMonth = 30;\\n } else {\\n daysInMonth = _isLeapYear(year) ? 29 : 28;\\n }\\n }\\n\\n // 1 = Monday, 7 = Sunday\\n function getDayOfWeek(uint timestamp)\\n internal\\n pure\\n returns (uint dayOfWeek)\\n {\\n uint _days = timestamp / SECONDS_PER_DAY;\\n dayOfWeek = ((_days + 3) % 7) + 1;\\n }\\n\\n function getYear(uint timestamp) internal pure returns (uint year) {\\n (year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n }\\n\\n function getMonth(uint timestamp) internal pure returns (uint month) {\\n (, month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n }\\n\\n function getDay(uint timestamp) internal pure returns (uint day) {\\n (, , day) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n }\\n\\n function getHour(uint timestamp) internal pure returns (uint hour) {\\n uint secs = timestamp % SECONDS_PER_DAY;\\n hour = secs / SECONDS_PER_HOUR;\\n }\\n\\n function getMinute(uint timestamp) internal pure returns (uint minute) {\\n uint secs = timestamp % SECONDS_PER_HOUR;\\n minute = secs / SECONDS_PER_MINUTE;\\n }\\n\\n function getSecond(uint timestamp) internal pure returns (uint second) {\\n second = timestamp % SECONDS_PER_MINUTE;\\n }\\n\\n function addYears(uint timestamp, uint _years)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n (uint year, uint month, uint day) = _daysToDate(\\n timestamp / SECONDS_PER_DAY\\n );\\n year += _years;\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > daysInMonth) {\\n day = daysInMonth;\\n }\\n newTimestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n (timestamp % SECONDS_PER_DAY);\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addMonths(uint timestamp, uint _months)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n (uint year, uint month, uint day) = _daysToDate(\\n timestamp / SECONDS_PER_DAY\\n );\\n month += _months;\\n year += (month - 1) / 12;\\n month = ((month - 1) % 12) + 1;\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > daysInMonth) {\\n day = daysInMonth;\\n }\\n newTimestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n (timestamp % SECONDS_PER_DAY);\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addDays(uint timestamp, uint _days)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp + _days * SECONDS_PER_DAY;\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addHours(uint timestamp, uint _hours)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addMinutes(uint timestamp, uint _minutes)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addSeconds(uint timestamp, uint _seconds)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp + _seconds;\\n require(newTimestamp >= timestamp);\\n }\\n\\n function subYears(uint timestamp, uint _years)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n (uint year, uint month, uint day) = _daysToDate(\\n timestamp / SECONDS_PER_DAY\\n );\\n year -= _years;\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > daysInMonth) {\\n day = daysInMonth;\\n }\\n newTimestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n (timestamp % SECONDS_PER_DAY);\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subMonths(uint timestamp, uint _months)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n (uint year, uint month, uint day) = _daysToDate(\\n timestamp / SECONDS_PER_DAY\\n );\\n uint yearMonth = year * 12 + (month - 1) - _months;\\n year = yearMonth / 12;\\n month = (yearMonth % 12) + 1;\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > daysInMonth) {\\n day = daysInMonth;\\n }\\n newTimestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n (timestamp % SECONDS_PER_DAY);\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subDays(uint timestamp, uint _days)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp - _days * SECONDS_PER_DAY;\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subHours(uint timestamp, uint _hours)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subMinutes(uint timestamp, uint _minutes)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subSeconds(uint timestamp, uint _seconds)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp - _seconds;\\n require(newTimestamp <= timestamp);\\n }\\n\\n function diffYears(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _years)\\n {\\n require(fromTimestamp <= toTimestamp);\\n (uint fromYear, , ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\\n (uint toYear, , ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\\n _years = toYear - fromYear;\\n }\\n\\n function diffMonths(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _months)\\n {\\n require(fromTimestamp <= toTimestamp);\\n (uint fromYear, uint fromMonth, ) = _daysToDate(\\n fromTimestamp / SECONDS_PER_DAY\\n );\\n (uint toYear, uint toMonth, ) = _daysToDate(\\n toTimestamp / SECONDS_PER_DAY\\n );\\n _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;\\n }\\n\\n function diffDays(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _days)\\n {\\n require(fromTimestamp <= toTimestamp);\\n _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;\\n }\\n\\n function diffHours(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _hours)\\n {\\n require(fromTimestamp <= toTimestamp);\\n _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;\\n }\\n\\n function diffMinutes(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _minutes)\\n {\\n require(fromTimestamp <= toTimestamp);\\n _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;\\n }\\n\\n function diffSeconds(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _seconds)\\n {\\n require(fromTimestamp <= toTimestamp);\\n _seconds = toTimestamp - fromTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0xf194df8ea9946a5bb3300223629b7e4959c1f20bacba27b3dc5f6dd2a160147a\",\"license\":\"MIT\"},\"contracts/libraries/NumbersLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n// Libraries\\nimport { SafeCast } from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport { Math } from \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"./WadRayMath.sol\\\";\\n\\n/**\\n * @dev Utility library for uint256 numbers\\n *\\n * @author develop@teller.finance\\n */\\nlibrary NumbersLib {\\n using WadRayMath for uint256;\\n\\n /**\\n * @dev It represents 100% with 2 decimal places.\\n */\\n uint16 internal constant PCT_100 = 10000;\\n\\n function percentFactor(uint256 decimals) internal pure returns (uint256) {\\n return 100 * (10**decimals);\\n }\\n\\n /**\\n * @notice Returns a percentage value of a number.\\n * @param self The number to get a percentage of.\\n * @param percentage The percentage value to calculate with 2 decimal places (10000 = 100%).\\n */\\n function percent(uint256 self, uint16 percentage)\\n internal\\n pure\\n returns (uint256)\\n {\\n return percent(self, percentage, 2);\\n }\\n\\n /**\\n * @notice Returns a percentage value of a number.\\n * @param self The number to get a percentage of.\\n * @param percentage The percentage value to calculate with.\\n * @param decimals The number of decimals the percentage value is in.\\n */\\n function percent(uint256 self, uint256 percentage, uint256 decimals)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (self * percentage) / percentFactor(decimals);\\n }\\n\\n /**\\n * @notice it returns the absolute number of a specified parameter\\n * @param self the number to be returned in it's absolute\\n * @return the absolute number\\n */\\n function abs(int256 self) internal pure returns (uint256) {\\n return self >= 0 ? uint256(self) : uint256(-1 * self);\\n }\\n\\n /**\\n * @notice Returns a ratio percentage of {num1} to {num2}.\\n * @dev Returned value is type uint16.\\n * @param num1 The number used to get the ratio for.\\n * @param num2 The number used to get the ratio from.\\n * @return Ratio percentage with 2 decimal places (10000 = 100%).\\n */\\n function ratioOf(uint256 num1, uint256 num2)\\n internal\\n pure\\n returns (uint16)\\n {\\n return SafeCast.toUint16(ratioOf(num1, num2, 2));\\n }\\n\\n /**\\n * @notice Returns a ratio percentage of {num1} to {num2}.\\n * @param num1 The number used to get the ratio for.\\n * @param num2 The number used to get the ratio from.\\n * @param decimals The number of decimals the percentage value is returned in.\\n * @return Ratio percentage value.\\n */\\n function ratioOf(uint256 num1, uint256 num2, uint256 decimals)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (num2 == 0) return 0;\\n return (num1 * percentFactor(decimals)) / num2;\\n }\\n\\n /**\\n * @notice Calculates the payment amount for a cycle duration.\\n * The formula is calculated based on the standard Estimated Monthly Installment (https://en.wikipedia.org/wiki/Equated_monthly_installment)\\n * EMI = [P x R x (1+R)^N]/[(1+R)^N-1]\\n * @param principal The starting amount that is owed on the loan.\\n * @param loanDuration The length of the loan.\\n * @param cycleDuration The length of the loan's payment cycle.\\n * @param apr The annual percentage rate of the loan.\\n */\\n function pmt(\\n uint256 principal,\\n uint32 loanDuration,\\n uint32 cycleDuration,\\n uint16 apr,\\n uint256 daysInYear\\n ) internal pure returns (uint256) {\\n require(\\n loanDuration >= cycleDuration,\\n \\\"PMT: cycle duration < loan duration\\\"\\n );\\n if (apr == 0)\\n return\\n Math.mulDiv(\\n principal,\\n cycleDuration,\\n loanDuration,\\n Math.Rounding.Up\\n );\\n\\n // Number of payment cycles for the duration of the loan\\n uint256 n = Math.ceilDiv(loanDuration, cycleDuration);\\n\\n uint256 one = WadRayMath.wad();\\n uint256 r = WadRayMath.pctToWad(apr).wadMul(cycleDuration).wadDiv(\\n daysInYear\\n );\\n uint256 exp = (one + r).wadPow(n);\\n uint256 numerator = principal.wadMul(r).wadMul(exp);\\n uint256 denominator = exp - one;\\n\\n return numerator.wadDiv(denominator);\\n }\\n}\\n\",\"keccak256\":\"0x78009ffb3737ab7615a1e38a26635d6c06b65b7b7959af46d6ef840d220e70cf\",\"license\":\"MIT\"},\"contracts/libraries/V2Calculations.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n\\n// SPDX-License-Identifier: MIT\\n\\n// Libraries\\nimport \\\"./NumbersLib.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport { Bid } from \\\"../TellerV2Storage.sol\\\";\\nimport { BokkyPooBahsDateTimeLibrary as BPBDTL } from \\\"./DateTimeLib.sol\\\";\\n\\nenum PaymentType {\\n EMI,\\n Bullet\\n}\\n\\nenum PaymentCycleType {\\n Seconds,\\n Monthly\\n}\\n\\nlibrary V2Calculations {\\n using NumbersLib for uint256;\\n\\n /**\\n * @notice Returns the timestamp of the last payment made for a loan.\\n * @param _bid The loan bid struct to get the timestamp for.\\n */\\n function lastRepaidTimestamp(Bid storage _bid)\\n internal\\n view\\n returns (uint32)\\n {\\n return\\n _bid.loanDetails.lastRepaidTimestamp == 0\\n ? _bid.loanDetails.acceptedTimestamp\\n : _bid.loanDetails.lastRepaidTimestamp;\\n }\\n\\n /**\\n * @notice Calculates the amount owed for a loan.\\n * @param _bid The loan bid struct to get the owed amount for.\\n * @param _timestamp The timestamp at which to get the owed amount at.\\n * @param _paymentCycleType The payment cycle type of the loan (Seconds or Monthly).\\n */\\n function calculateAmountOwed(\\n Bid storage _bid,\\n uint256 _timestamp,\\n PaymentCycleType _paymentCycleType,\\n uint32 _paymentCycleDuration\\n )\\n public\\n view\\n returns (\\n uint256 owedPrincipal_,\\n uint256 duePrincipal_,\\n uint256 interest_\\n )\\n {\\n // Total principal left to pay\\n return\\n calculateAmountOwed(\\n _bid,\\n lastRepaidTimestamp(_bid),\\n _timestamp,\\n _paymentCycleType,\\n _paymentCycleDuration\\n );\\n }\\n\\n function calculateAmountOwed(\\n Bid storage _bid,\\n uint256 _lastRepaidTimestamp,\\n uint256 _timestamp,\\n PaymentCycleType _paymentCycleType,\\n uint32 _paymentCycleDuration\\n )\\n public\\n view\\n returns (\\n uint256 owedPrincipal_,\\n uint256 duePrincipal_,\\n uint256 interest_\\n )\\n {\\n owedPrincipal_ =\\n _bid.loanDetails.principal -\\n _bid.loanDetails.totalRepaid.principal;\\n\\n uint256 owedTime = _timestamp - uint256(_lastRepaidTimestamp);\\n\\n {\\n uint256 daysInYear = _paymentCycleType == PaymentCycleType.Monthly\\n ? 360 days\\n : 365 days;\\n\\n uint256 interestOwedInAYear = owedPrincipal_.percent(_bid.terms.APR, 2);\\n \\n interest_ = (interestOwedInAYear * owedTime) / daysInYear;\\n }\\n\\n\\n bool isLastPaymentCycle;\\n {\\n uint256 lastPaymentCycleDuration = _bid.loanDetails.loanDuration %\\n _paymentCycleDuration;\\n if (lastPaymentCycleDuration == 0) {\\n lastPaymentCycleDuration = _paymentCycleDuration;\\n }\\n\\n uint256 endDate = uint256(_bid.loanDetails.acceptedTimestamp) +\\n uint256(_bid.loanDetails.loanDuration);\\n uint256 lastPaymentCycleStart = endDate -\\n uint256(lastPaymentCycleDuration);\\n\\n isLastPaymentCycle =\\n uint256(_timestamp) > lastPaymentCycleStart ||\\n owedPrincipal_ + interest_ <= _bid.terms.paymentCycleAmount;\\n }\\n\\n if (_bid.paymentType == PaymentType.Bullet) {\\n if (isLastPaymentCycle) {\\n duePrincipal_ = owedPrincipal_;\\n }\\n } else {\\n // Default to PaymentType.EMI\\n // Max payable amount in a cycle\\n // NOTE: the last cycle could have less than the calculated payment amount\\n\\n //the amount owed for the cycle should never exceed the current payment cycle amount so we use min here \\n uint256 owedAmountForCycle = Math.min( ((_bid.terms.paymentCycleAmount * owedTime) ) /\\n _paymentCycleDuration , _bid.terms.paymentCycleAmount+interest_ ) ;\\n\\n uint256 owedAmount = isLastPaymentCycle\\n ? owedPrincipal_ + interest_\\n : owedAmountForCycle ;\\n\\n duePrincipal_ = Math.min(owedAmount - interest_, owedPrincipal_);\\n }\\n }\\n\\n /**\\n * @notice Calculates the amount owed for a loan for the next payment cycle.\\n * @param _type The payment type of the loan.\\n * @param _cycleType The cycle type set for the loan. (Seconds or Monthly)\\n * @param _principal The starting amount that is owed on the loan.\\n * @param _duration The length of the loan.\\n * @param _paymentCycle The length of the loan's payment cycle.\\n * @param _apr The annual percentage rate of the loan.\\n */\\n function calculatePaymentCycleAmount(\\n PaymentType _type,\\n PaymentCycleType _cycleType,\\n uint256 _principal,\\n uint32 _duration,\\n uint32 _paymentCycle,\\n uint16 _apr\\n ) public view returns (uint256) {\\n uint256 daysInYear = _cycleType == PaymentCycleType.Monthly\\n ? 360 days\\n : 365 days;\\n if (_type == PaymentType.Bullet) {\\n return\\n _principal.percent(_apr).percent(\\n uint256(_paymentCycle).ratioOf(daysInYear, 10),\\n 10\\n );\\n }\\n // Default to PaymentType.EMI\\n return\\n NumbersLib.pmt(\\n _principal,\\n _duration,\\n _paymentCycle,\\n _apr,\\n daysInYear\\n );\\n }\\n\\n function calculateNextDueDate(\\n uint32 _acceptedTimestamp,\\n uint32 _paymentCycle,\\n uint32 _loanDuration,\\n uint32 _lastRepaidTimestamp,\\n PaymentCycleType _bidPaymentCycleType\\n ) public view returns (uint32 dueDate_) {\\n // Calculate due date if payment cycle is set to monthly\\n if (_bidPaymentCycleType == PaymentCycleType.Monthly) {\\n // Calculate the cycle number the last repayment was made\\n uint256 lastPaymentCycle = BPBDTL.diffMonths(\\n _acceptedTimestamp,\\n _lastRepaidTimestamp\\n );\\n if (\\n BPBDTL.getDay(_lastRepaidTimestamp) >\\n BPBDTL.getDay(_acceptedTimestamp)\\n ) {\\n lastPaymentCycle += 2;\\n } else {\\n lastPaymentCycle += 1;\\n }\\n\\n dueDate_ = uint32(\\n BPBDTL.addMonths(_acceptedTimestamp, lastPaymentCycle)\\n );\\n } else if (_bidPaymentCycleType == PaymentCycleType.Seconds) {\\n // Start with the original due date being 1 payment cycle since bid was accepted\\n dueDate_ = _acceptedTimestamp + _paymentCycle;\\n // Calculate the cycle number the last repayment was made\\n uint32 delta = _lastRepaidTimestamp - _acceptedTimestamp;\\n if (delta > 0) {\\n uint32 repaymentCycle = uint32(\\n Math.ceilDiv(delta, _paymentCycle)\\n );\\n dueDate_ += (repaymentCycle * _paymentCycle);\\n }\\n }\\n\\n uint32 endOfLoan = _acceptedTimestamp + _loanDuration;\\n //if we are in the last payment cycle, the next due date is the end of loan duration\\n if (dueDate_ > endOfLoan) {\\n dueDate_ = endOfLoan;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8452535763bfb5c529a0089b8b669d77cc4e1e333b526b89b5d42ab491fb4312\",\"license\":\"MIT\"},\"contracts/libraries/WadRayMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\n/**\\n * @title WadRayMath library\\n * @author Multiplier Finance\\n * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits)\\n */\\nlibrary WadRayMath {\\n using SafeMath for uint256;\\n\\n uint256 internal constant WAD = 1e18;\\n uint256 internal constant halfWAD = WAD / 2;\\n\\n uint256 internal constant RAY = 1e27;\\n uint256 internal constant halfRAY = RAY / 2;\\n\\n uint256 internal constant WAD_RAY_RATIO = 1e9;\\n uint256 internal constant PCT_WAD_RATIO = 1e14;\\n uint256 internal constant PCT_RAY_RATIO = 1e23;\\n\\n function ray() internal pure returns (uint256) {\\n return RAY;\\n }\\n\\n function wad() internal pure returns (uint256) {\\n return WAD;\\n }\\n\\n function halfRay() internal pure returns (uint256) {\\n return halfRAY;\\n }\\n\\n function halfWad() internal pure returns (uint256) {\\n return halfWAD;\\n }\\n\\n function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return halfWAD.add(a.mul(b)).div(WAD);\\n }\\n\\n function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 halfB = b / 2;\\n\\n return halfB.add(a.mul(WAD)).div(b);\\n }\\n\\n function rayMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return halfRAY.add(a.mul(b)).div(RAY);\\n }\\n\\n function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 halfB = b / 2;\\n\\n return halfB.add(a.mul(RAY)).div(b);\\n }\\n\\n function rayToWad(uint256 a) internal pure returns (uint256) {\\n uint256 halfRatio = WAD_RAY_RATIO / 2;\\n\\n return halfRatio.add(a).div(WAD_RAY_RATIO);\\n }\\n\\n function rayToPct(uint256 a) internal pure returns (uint16) {\\n uint256 halfRatio = PCT_RAY_RATIO / 2;\\n\\n uint256 val = halfRatio.add(a).div(PCT_RAY_RATIO);\\n return SafeCast.toUint16(val);\\n }\\n\\n function wadToPct(uint256 a) internal pure returns (uint16) {\\n uint256 halfRatio = PCT_WAD_RATIO / 2;\\n\\n uint256 val = halfRatio.add(a).div(PCT_WAD_RATIO);\\n return SafeCast.toUint16(val);\\n }\\n\\n function wadToRay(uint256 a) internal pure returns (uint256) {\\n return a.mul(WAD_RAY_RATIO);\\n }\\n\\n function pctToRay(uint16 a) internal pure returns (uint256) {\\n return uint256(a).mul(RAY).div(1e4);\\n }\\n\\n function pctToWad(uint16 a) internal pure returns (uint256) {\\n return uint256(a).mul(WAD).div(1e4);\\n }\\n\\n /**\\n * @dev calculates base^duration. The code uses the ModExp precompile\\n * @return z base^duration, in ray\\n */\\n function rayPow(uint256 x, uint256 n) internal pure returns (uint256) {\\n return _pow(x, n, RAY, rayMul);\\n }\\n\\n function wadPow(uint256 x, uint256 n) internal pure returns (uint256) {\\n return _pow(x, n, WAD, wadMul);\\n }\\n\\n function _pow(\\n uint256 x,\\n uint256 n,\\n uint256 p,\\n function(uint256, uint256) internal pure returns (uint256) mul\\n ) internal pure returns (uint256 z) {\\n z = n % 2 != 0 ? x : p;\\n\\n for (n /= 2; n != 0; n /= 2) {\\n x = mul(x, x);\\n\\n if (n % 2 != 0) {\\n z = mul(z, x);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2781319be7a96f56966c601c061849fa94dbf9af5ad80a20c40b879a8d03f14a\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x61139261003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100555760003560e01c80628945b51461005a5780630dcf1658146100805780635ab17296146100a8578063e4de10d3146100d6575b600080fd5b61006d610068366004610e66565b6100e9565b6040519081526020015b60405180910390f35b61009361008e366004610ee2565b610187565b60405163ffffffff9091168152602001610077565b6100bb6100b6366004610f4b565b6102bd565b60408051938452602084019290925290820152606001610077565b6100bb6100e4366004610f9d565b6104a8565b600080600187600181111561010057610100610fe5565b1461010f576301e13380610115565b6301da9c005b63ffffffff169050600188600181111561013157610131610fe5565b141561016c5761016461015163ffffffff808716908490600a906104d816565b600a61015d898761050f565b919061052a565b91505061017d565b610179868686868561053f565b9150505b9695505050505050565b6000600182600181111561019d5761019d610fe5565b14156102195760006101bb8763ffffffff168563ffffffff16610674565b90506101cc8763ffffffff166106fb565b6101db8563ffffffff166106fb565b11156101f3576101ec600282611011565b9050610201565b6101fe600182611011565b90505b6102118763ffffffff1682610715565b91505061028d565b600082600181111561022d5761022d610fe5565b141561028d5761023d8587611029565b9050600061024b8785611051565b905063ffffffff81161561028b5760006102718263ffffffff168863ffffffff166107e7565b905061027d8782611076565b6102879084611029565b9250505b505b60006102998588611029565b90508063ffffffff168263ffffffff1611156102b3578091505b5095945050505050565b60078501546006860154600091829182916102d7916110a2565b925060006102e588886110a2565b9050600060018760018111156102fd576102fd610fe5565b1461030c576301e13380610312565b6301da9c005b600b8b015463ffffffff918216925060009161034191889164010000000090910461ffff169060029061052a16565b90508161034e84836110b9565b61035891906110ee565b60098c01549094506000925082915061037f908890600160601b900463ffffffff16611102565b63ffffffff16905080610395575063ffffffff86165b60098b01546000906103be9063ffffffff600160601b8204811691640100000000900416611011565b905060006103cc83836110a2565b9050808b11806103e95750600a8d01546103e6878a611011565b11155b9350600192506103f7915050565b600c8b0154610100900460ff16600181111561041557610415610fe5565b141561042a578015610425578493505b61049b565b60006104688763ffffffff16848d600a016000015461044991906110b9565b61045391906110ee565b600a8d0154610463908790611011565b61081e565b90506000826104775781610481565b6104818588611011565b905061049661049086836110a2565b8861081e565b955050505b5050955095509592505050565b60008060006104c8876104ba89610834565b63ffffffff168888886102bd565b9250925092509450945094915050565b6000826104e757506000610508565b826104f18361087b565b6104fb90866110b9565b61050591906110ee565b90505b9392505050565b6000610521838361ffff16600261052a565b90505b92915050565b60006105358261087b565b6104fb84866110b9565b60008363ffffffff168563ffffffff1610156105ad5760405162461bcd60e51b815260206004820152602360248201527f504d543a206379636c65206475726174696f6e203c206c6f616e20647572617460448201526234b7b760e91b606482015260840160405180910390fd5b61ffff83166105d6576105cf868563ffffffff168763ffffffff166001610893565b905061066b565b60006105ee8663ffffffff168663ffffffff166107e7565b9050670de0b6b3a7640000600061061e8561061863ffffffff8a166106128a6108e4565b90610908565b9061093c565b90506000610636846106308486611011565b9061096c565b90506000610648826106128d86610908565b9050600061065685846110a2565b9050610662828261093c565b96505050505050505b95945050505050565b60008183111561068357600080fd5b60008061069b61069662015180876110ee565b610984565b5090925090506000806106b461069662015180886110ee565b509092509050826106c685600c6110b9565b826106d285600c6110b9565b6106dc9190611011565b6106e691906110a2565b6106f091906110a2565b979650505050505050565b600061070d61069662015180846110ee565b949350505050565b600080808061072a61069662015180886110ee565b9194509250905061073b8583611011565b9150600c61074a6001846110a2565b61075491906110ee565b61075e9084611011565b9250600c61076d6001846110a2565b6107779190611125565b610782906001611011565b915060006107908484610af8565b90508082111561079e578091505b6107ab6201518088611125565b620151806107ba868686610b7e565b6107c491906110b9565b6107ce9190611011565b9450868510156107dd57600080fd5b5050505092915050565b6000821561081557816107fb6001856110a2565b61080591906110ee565b610810906001611011565b610521565b50600092915050565b600081831061082d5781610521565b5090919050565b6009810154600090600160401b900463ffffffff1615610865576009820154600160401b900463ffffffff16610524565b5060090154640100000000900463ffffffff1690565b600061088882600a61121d565b6105249060646110b9565b6000806108a1868686610cbb565b905060018360028111156108b7576108b7610fe5565b1480156108d45750600084806108cf576108cf6110d8565b868809115b1561066b5761017d600182611011565b600061052461271061090261ffff8516670de0b6b3a7640000610d6b565b90610d77565b6000610521670de0b6b3a76400006109026109238686610d6b565b6109366002670de0b6b3a76400006110ee565b90610d83565b60008061094a6002846110ee565b905061070d8361090261096587670de0b6b3a7640000610d6b565b8490610d83565b60006105218383670de0b6b3a7640000610908610d8f565b60008080838162253d8c61099b8362010bd9611229565b6109a59190611229565b9050600062023ab16109b883600461126a565b6109c291906112ef565b905060046109d38262023ab161126a565b6109de906003611229565b6109e891906112ef565b6109f2908361131d565b9150600062164b09610a05846001611229565b610a1190610fa061126a565b610a1b91906112ef565b90506004610a2b826105b561126a565b610a3591906112ef565b610a3f908461131d565b610a4a90601f611229565b9250600061098f610a5c85605061126a565b610a6691906112ef565b905060006050610a788361098f61126a565b610a8291906112ef565b610a8c908661131d565b9050610a99600b836112ef565b9450610aa685600c61126a565b610ab1836002611229565b610abb919061131d565b91508483610aca60318761131d565b610ad590606461126a565b610adf9190611229565b610ae99190611229565b9a919950975095505050505050565b60008160011480610b095750816003145b80610b145750816005145b80610b1f5750816007145b80610b2a5750816008145b80610b35575081600a145b80610b40575081600c145b15610b4d5750601f610524565b81600214610b5d5750601e610524565b610b6683610e01565b610b7157601c610b74565b601d5b60ff169392505050565b60006107b2841015610b8f57600080fd5b838383600062253d8c60046064600c610ba9600e8861131d565b610bb391906112ef565b610bbf88611324611229565b610bc99190611229565b610bd391906112ef565b610bde90600361126a565b610be891906112ef565b600c80610bf6600e8861131d565b610c0091906112ef565b610c0b90600c61126a565b610c1660028861131d565b610c20919061131d565b610c2c9061016f61126a565b610c3691906112ef565b6004600c610c45600e8961131d565b610c4f91906112ef565b610c5b896112c0611229565b610c659190611229565b610c71906105b561126a565b610c7b91906112ef565b610c87617d4b8761131d565b610c919190611229565b610c9b9190611229565b610ca5919061131d565b610caf919061131d565b98975050505050505050565b600080806000198587098587029250828110838203039150508060001415610cf657838281610cec57610cec6110d8565b0492505050610508565b808411610d0257600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600061052182846110b9565b600061052182846110ee565b60006105218284611011565b6000610d9c600285611125565b610da65782610da8565b845b9050610db56002856110ee565b93505b831561070d57610dcc85868463ffffffff16565b9450610dd9600285611125565b15610def57610dec81868463ffffffff16565b90505b610dfa6002856110ee565b9350610db8565b6000610e0e600483611125565b158015610e245750610e21606483611125565b15155b806105245750610e3661019083611125565b1592915050565b60028110610e4a57600080fd5b50565b803563ffffffff81168114610e6157600080fd5b919050565b60008060008060008060c08789031215610e7f57600080fd5b8635610e8a81610e3d565b95506020870135610e9a81610e3d565b945060408701359350610eaf60608801610e4d565b9250610ebd60808801610e4d565b915060a087013561ffff81168114610ed457600080fd5b809150509295509295509295565b600080600080600060a08688031215610efa57600080fd5b610f0386610e4d565b9450610f1160208701610e4d565b9350610f1f60408701610e4d565b9250610f2d60608701610e4d565b91506080860135610f3d81610e3d565b809150509295509295909350565b600080600080600060a08688031215610f6357600080fd5b8535945060208601359350604086013592506060860135610f8381610e3d565b9150610f9160808701610e4d565b90509295509295909350565b60008060008060808587031215610fb357600080fd5b84359350602085013592506040850135610fcc81610e3d565b9150610fda60608601610e4d565b905092959194509250565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561102457611024610ffb565b500190565b600063ffffffff80831681851680830382111561104857611048610ffb565b01949350505050565b600063ffffffff8381169083168181101561106e5761106e610ffb565b039392505050565b600063ffffffff8083168185168183048111821515161561109957611099610ffb565b02949350505050565b6000828210156110b4576110b4610ffb565b500390565b60008160001904831182151516156110d3576110d3610ffb565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826110fd576110fd6110d8565b500490565b600063ffffffff80841680611119576111196110d8565b92169190910692915050565b600082611134576111346110d8565b500690565b600181815b8085111561117457816000190482111561115a5761115a610ffb565b8085161561116757918102915b93841c939080029061113e565b509250929050565b60008261118b57506001610524565b8161119857506000610524565b81600181146111ae57600281146111b8576111d4565b6001915050610524565b60ff8411156111c9576111c9610ffb565b50506001821b610524565b5060208310610133831016604e8410600b84101617156111f7575081810a610524565b6112018383611139565b806000190482111561121557611215610ffb565b029392505050565b6000610521838361117c565b600080821280156001600160ff1b038490038513161561124b5761124b610ffb565b600160ff1b839003841281161561126457611264610ffb565b50500190565b60006001600160ff1b038184138284138082168684048611161561129057611290610ffb565b600160ff1b60008712828116878305891216156112af576112af610ffb565b600087129250878205871284841616156112cb576112cb610ffb565b878505871281841616156112e1576112e1610ffb565b505050929093029392505050565b6000826112fe576112fe6110d8565b600160ff1b82146000198414161561131857611318610ffb565b500590565b60008083128015600160ff1b85018412161561133b5761133b610ffb565b6001600160ff1b038401831381161561135657611356610ffb565b5050039056fea2646970667358221220919c19a319e330785d342ba3bd86c1c2afc39a749a6d2df82516d60bb3b0063d64736f6c63430008090033", - "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100555760003560e01c80628945b51461005a5780630dcf1658146100805780635ab17296146100a8578063e4de10d3146100d6575b600080fd5b61006d610068366004610e66565b6100e9565b6040519081526020015b60405180910390f35b61009361008e366004610ee2565b610187565b60405163ffffffff9091168152602001610077565b6100bb6100b6366004610f4b565b6102bd565b60408051938452602084019290925290820152606001610077565b6100bb6100e4366004610f9d565b6104a8565b600080600187600181111561010057610100610fe5565b1461010f576301e13380610115565b6301da9c005b63ffffffff169050600188600181111561013157610131610fe5565b141561016c5761016461015163ffffffff808716908490600a906104d816565b600a61015d898761050f565b919061052a565b91505061017d565b610179868686868561053f565b9150505b9695505050505050565b6000600182600181111561019d5761019d610fe5565b14156102195760006101bb8763ffffffff168563ffffffff16610674565b90506101cc8763ffffffff166106fb565b6101db8563ffffffff166106fb565b11156101f3576101ec600282611011565b9050610201565b6101fe600182611011565b90505b6102118763ffffffff1682610715565b91505061028d565b600082600181111561022d5761022d610fe5565b141561028d5761023d8587611029565b9050600061024b8785611051565b905063ffffffff81161561028b5760006102718263ffffffff168863ffffffff166107e7565b905061027d8782611076565b6102879084611029565b9250505b505b60006102998588611029565b90508063ffffffff168263ffffffff1611156102b3578091505b5095945050505050565b60078501546006860154600091829182916102d7916110a2565b925060006102e588886110a2565b9050600060018760018111156102fd576102fd610fe5565b1461030c576301e13380610312565b6301da9c005b600b8b015463ffffffff918216925060009161034191889164010000000090910461ffff169060029061052a16565b90508161034e84836110b9565b61035891906110ee565b60098c01549094506000925082915061037f908890600160601b900463ffffffff16611102565b63ffffffff16905080610395575063ffffffff86165b60098b01546000906103be9063ffffffff600160601b8204811691640100000000900416611011565b905060006103cc83836110a2565b9050808b11806103e95750600a8d01546103e6878a611011565b11155b9350600192506103f7915050565b600c8b0154610100900460ff16600181111561041557610415610fe5565b141561042a578015610425578493505b61049b565b60006104688763ffffffff16848d600a016000015461044991906110b9565b61045391906110ee565b600a8d0154610463908790611011565b61081e565b90506000826104775781610481565b6104818588611011565b905061049661049086836110a2565b8861081e565b955050505b5050955095509592505050565b60008060006104c8876104ba89610834565b63ffffffff168888886102bd565b9250925092509450945094915050565b6000826104e757506000610508565b826104f18361087b565b6104fb90866110b9565b61050591906110ee565b90505b9392505050565b6000610521838361ffff16600261052a565b90505b92915050565b60006105358261087b565b6104fb84866110b9565b60008363ffffffff168563ffffffff1610156105ad5760405162461bcd60e51b815260206004820152602360248201527f504d543a206379636c65206475726174696f6e203c206c6f616e20647572617460448201526234b7b760e91b606482015260840160405180910390fd5b61ffff83166105d6576105cf868563ffffffff168763ffffffff166001610893565b905061066b565b60006105ee8663ffffffff168663ffffffff166107e7565b9050670de0b6b3a7640000600061061e8561061863ffffffff8a166106128a6108e4565b90610908565b9061093c565b90506000610636846106308486611011565b9061096c565b90506000610648826106128d86610908565b9050600061065685846110a2565b9050610662828261093c565b96505050505050505b95945050505050565b60008183111561068357600080fd5b60008061069b61069662015180876110ee565b610984565b5090925090506000806106b461069662015180886110ee565b509092509050826106c685600c6110b9565b826106d285600c6110b9565b6106dc9190611011565b6106e691906110a2565b6106f091906110a2565b979650505050505050565b600061070d61069662015180846110ee565b949350505050565b600080808061072a61069662015180886110ee565b9194509250905061073b8583611011565b9150600c61074a6001846110a2565b61075491906110ee565b61075e9084611011565b9250600c61076d6001846110a2565b6107779190611125565b610782906001611011565b915060006107908484610af8565b90508082111561079e578091505b6107ab6201518088611125565b620151806107ba868686610b7e565b6107c491906110b9565b6107ce9190611011565b9450868510156107dd57600080fd5b5050505092915050565b6000821561081557816107fb6001856110a2565b61080591906110ee565b610810906001611011565b610521565b50600092915050565b600081831061082d5781610521565b5090919050565b6009810154600090600160401b900463ffffffff1615610865576009820154600160401b900463ffffffff16610524565b5060090154640100000000900463ffffffff1690565b600061088882600a61121d565b6105249060646110b9565b6000806108a1868686610cbb565b905060018360028111156108b7576108b7610fe5565b1480156108d45750600084806108cf576108cf6110d8565b868809115b1561066b5761017d600182611011565b600061052461271061090261ffff8516670de0b6b3a7640000610d6b565b90610d77565b6000610521670de0b6b3a76400006109026109238686610d6b565b6109366002670de0b6b3a76400006110ee565b90610d83565b60008061094a6002846110ee565b905061070d8361090261096587670de0b6b3a7640000610d6b565b8490610d83565b60006105218383670de0b6b3a7640000610908610d8f565b60008080838162253d8c61099b8362010bd9611229565b6109a59190611229565b9050600062023ab16109b883600461126a565b6109c291906112ef565b905060046109d38262023ab161126a565b6109de906003611229565b6109e891906112ef565b6109f2908361131d565b9150600062164b09610a05846001611229565b610a1190610fa061126a565b610a1b91906112ef565b90506004610a2b826105b561126a565b610a3591906112ef565b610a3f908461131d565b610a4a90601f611229565b9250600061098f610a5c85605061126a565b610a6691906112ef565b905060006050610a788361098f61126a565b610a8291906112ef565b610a8c908661131d565b9050610a99600b836112ef565b9450610aa685600c61126a565b610ab1836002611229565b610abb919061131d565b91508483610aca60318761131d565b610ad590606461126a565b610adf9190611229565b610ae99190611229565b9a919950975095505050505050565b60008160011480610b095750816003145b80610b145750816005145b80610b1f5750816007145b80610b2a5750816008145b80610b35575081600a145b80610b40575081600c145b15610b4d5750601f610524565b81600214610b5d5750601e610524565b610b6683610e01565b610b7157601c610b74565b601d5b60ff169392505050565b60006107b2841015610b8f57600080fd5b838383600062253d8c60046064600c610ba9600e8861131d565b610bb391906112ef565b610bbf88611324611229565b610bc99190611229565b610bd391906112ef565b610bde90600361126a565b610be891906112ef565b600c80610bf6600e8861131d565b610c0091906112ef565b610c0b90600c61126a565b610c1660028861131d565b610c20919061131d565b610c2c9061016f61126a565b610c3691906112ef565b6004600c610c45600e8961131d565b610c4f91906112ef565b610c5b896112c0611229565b610c659190611229565b610c71906105b561126a565b610c7b91906112ef565b610c87617d4b8761131d565b610c919190611229565b610c9b9190611229565b610ca5919061131d565b610caf919061131d565b98975050505050505050565b600080806000198587098587029250828110838203039150508060001415610cf657838281610cec57610cec6110d8565b0492505050610508565b808411610d0257600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600061052182846110b9565b600061052182846110ee565b60006105218284611011565b6000610d9c600285611125565b610da65782610da8565b845b9050610db56002856110ee565b93505b831561070d57610dcc85868463ffffffff16565b9450610dd9600285611125565b15610def57610dec81868463ffffffff16565b90505b610dfa6002856110ee565b9350610db8565b6000610e0e600483611125565b158015610e245750610e21606483611125565b15155b806105245750610e3661019083611125565b1592915050565b60028110610e4a57600080fd5b50565b803563ffffffff81168114610e6157600080fd5b919050565b60008060008060008060c08789031215610e7f57600080fd5b8635610e8a81610e3d565b95506020870135610e9a81610e3d565b945060408701359350610eaf60608801610e4d565b9250610ebd60808801610e4d565b915060a087013561ffff81168114610ed457600080fd5b809150509295509295509295565b600080600080600060a08688031215610efa57600080fd5b610f0386610e4d565b9450610f1160208701610e4d565b9350610f1f60408701610e4d565b9250610f2d60608701610e4d565b91506080860135610f3d81610e3d565b809150509295509295909350565b600080600080600060a08688031215610f6357600080fd5b8535945060208601359350604086013592506060860135610f8381610e3d565b9150610f9160808701610e4d565b90509295509295909350565b60008060008060808587031215610fb357600080fd5b84359350602085013592506040850135610fcc81610e3d565b9150610fda60608601610e4d565b905092959194509250565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561102457611024610ffb565b500190565b600063ffffffff80831681851680830382111561104857611048610ffb565b01949350505050565b600063ffffffff8381169083168181101561106e5761106e610ffb565b039392505050565b600063ffffffff8083168185168183048111821515161561109957611099610ffb565b02949350505050565b6000828210156110b4576110b4610ffb565b500390565b60008160001904831182151516156110d3576110d3610ffb565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826110fd576110fd6110d8565b500490565b600063ffffffff80841680611119576111196110d8565b92169190910692915050565b600082611134576111346110d8565b500690565b600181815b8085111561117457816000190482111561115a5761115a610ffb565b8085161561116757918102915b93841c939080029061113e565b509250929050565b60008261118b57506001610524565b8161119857506000610524565b81600181146111ae57600281146111b8576111d4565b6001915050610524565b60ff8411156111c9576111c9610ffb565b50506001821b610524565b5060208310610133831016604e8410600b84101617156111f7575081810a610524565b6112018383611139565b806000190482111561121557611215610ffb565b029392505050565b6000610521838361117c565b600080821280156001600160ff1b038490038513161561124b5761124b610ffb565b600160ff1b839003841281161561126457611264610ffb565b50500190565b60006001600160ff1b038184138284138082168684048611161561129057611290610ffb565b600160ff1b60008712828116878305891216156112af576112af610ffb565b600087129250878205871284841616156112cb576112cb610ffb565b878505871281841616156112e1576112e1610ffb565b505050929093029392505050565b6000826112fe576112fe6110d8565b600160ff1b82146000198414161561131857611318610ffb565b500590565b60008083128015600160ff1b85018412161561133b5761133b610ffb565b6001600160ff1b038401831381161561135657611356610ffb565b5050039056fea2646970667358221220919c19a319e330785d342ba3bd86c1c2afc39a749a6d2df82516d60bb3b0063d64736f6c63430008090033", + "numDeployments": 8, + "solcInputHash": "e99b722e6618936643bdf6ab83e66ac0", + "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_acceptedTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_paymentCycle\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_loanDuration\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_lastRepaidTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"enum PaymentCycleType\",\"name\":\"_bidPaymentCycleType\",\"type\":\"PaymentCycleType\"}],\"name\":\"calculateNextDueDate\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"dueDate_\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum PaymentType\",\"name\":\"_type\",\"type\":\"PaymentType\"},{\"internalType\":\"enum PaymentCycleType\",\"name\":\"_cycleType\",\"type\":\"PaymentCycleType\"},{\"internalType\":\"uint256\",\"name\":\"_principal\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_duration\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_paymentCycle\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_apr\",\"type\":\"uint16\"}],\"name\":\"calculatePaymentCycleAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateAmountOwed(Bid storage,uint256,PaymentCycleType,uint32)\":{\"params\":{\"_bid\":\"The loan bid struct to get the owed amount for.\",\"_paymentCycleType\":\"The payment cycle type of the loan (Seconds or Monthly).\",\"_timestamp\":\"The timestamp at which to get the owed amount at.\"}},\"calculatePaymentCycleAmount(PaymentType,PaymentCycleType,uint256,uint32,uint32,uint16)\":{\"params\":{\"_apr\":\"The annual percentage rate of the loan.\",\"_cycleType\":\"The cycle type set for the loan. (Seconds or Monthly)\",\"_duration\":\"The length of the loan.\",\"_paymentCycle\":\"The length of the loan's payment cycle.\",\"_principal\":\"The starting amount that is owed on the loan.\",\"_type\":\"The payment type of the loan.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateAmountOwed(Bid storage,uint256,PaymentCycleType,uint32)\":{\"notice\":\"Calculates the amount owed for a loan.\"},\"calculatePaymentCycleAmount(PaymentType,PaymentCycleType,uint256,uint32,uint32,uint16)\":{\"notice\":\"Calculates the amount owed for a loan for the next payment cycle.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/V2Calculations.sol\":\"V2Calculations\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165Upgradeable.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721Upgradeable is IERC165Upgradeable {\\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`.\\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 /**\\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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\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 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 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 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\",\"keccak256\":\"0x2c0b89cef83f353c6f9488c013d8a5968587ffdd6dfc26aad53774214b97e229\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.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 IERC165Upgradeable {\\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\":\"0xc6cef87559d0aeffdf0a99803de655938a7779ec0a3cd5d4383483ad85565a09\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (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 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 /**\\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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\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 return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\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\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\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 /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint248 from uint256, reverting on\\n * overflow (when the input is greater than largest uint248).\\n *\\n * Counterpart to Solidity's `uint248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint248(uint256 value) internal pure returns (uint248) {\\n require(value <= type(uint248).max, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n return uint248(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint240 from uint256, reverting on\\n * overflow (when the input is greater than largest uint240).\\n *\\n * Counterpart to Solidity's `uint240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint240(uint256 value) internal pure returns (uint240) {\\n require(value <= type(uint240).max, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n return uint240(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint232 from uint256, reverting on\\n * overflow (when the input is greater than largest uint232).\\n *\\n * Counterpart to Solidity's `uint232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint232(uint256 value) internal pure returns (uint232) {\\n require(value <= type(uint232).max, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n return uint232(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint216 from uint256, reverting on\\n * overflow (when the input is greater than largest uint216).\\n *\\n * Counterpart to Solidity's `uint216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint216(uint256 value) internal pure returns (uint216) {\\n require(value <= type(uint216).max, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n return uint216(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint208 from uint256, reverting on\\n * overflow (when the input is greater than largest uint208).\\n *\\n * Counterpart to Solidity's `uint208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint208(uint256 value) internal pure returns (uint208) {\\n require(value <= type(uint208).max, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n return uint208(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint200 from uint256, reverting on\\n * overflow (when the input is greater than largest uint200).\\n *\\n * Counterpart to Solidity's `uint200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint200(uint256 value) internal pure returns (uint200) {\\n require(value <= type(uint200).max, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n return uint200(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint192 from uint256, reverting on\\n * overflow (when the input is greater than largest uint192).\\n *\\n * Counterpart to Solidity's `uint192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint192(uint256 value) internal pure returns (uint192) {\\n require(value <= type(uint192).max, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n return uint192(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint184 from uint256, reverting on\\n * overflow (when the input is greater than largest uint184).\\n *\\n * Counterpart to Solidity's `uint184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint184(uint256 value) internal pure returns (uint184) {\\n require(value <= type(uint184).max, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n return uint184(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint176 from uint256, reverting on\\n * overflow (when the input is greater than largest uint176).\\n *\\n * Counterpart to Solidity's `uint176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint176(uint256 value) internal pure returns (uint176) {\\n require(value <= type(uint176).max, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n return uint176(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint168 from uint256, reverting on\\n * overflow (when the input is greater than largest uint168).\\n *\\n * Counterpart to Solidity's `uint168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint168(uint256 value) internal pure returns (uint168) {\\n require(value <= type(uint168).max, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n return uint168(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint160 from uint256, reverting on\\n * overflow (when the input is greater than largest uint160).\\n *\\n * Counterpart to Solidity's `uint160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint160(uint256 value) internal pure returns (uint160) {\\n require(value <= type(uint160).max, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n return uint160(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint152 from uint256, reverting on\\n * overflow (when the input is greater than largest uint152).\\n *\\n * Counterpart to Solidity's `uint152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint152(uint256 value) internal pure returns (uint152) {\\n require(value <= type(uint152).max, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n return uint152(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint144 from uint256, reverting on\\n * overflow (when the input is greater than largest uint144).\\n *\\n * Counterpart to Solidity's `uint144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint144(uint256 value) internal pure returns (uint144) {\\n require(value <= type(uint144).max, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n return uint144(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint136 from uint256, reverting on\\n * overflow (when the input is greater than largest uint136).\\n *\\n * Counterpart to Solidity's `uint136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint136(uint256 value) internal pure returns (uint136) {\\n require(value <= type(uint136).max, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n return uint136(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint120 from uint256, reverting on\\n * overflow (when the input is greater than largest uint120).\\n *\\n * Counterpart to Solidity's `uint120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint120(uint256 value) internal pure returns (uint120) {\\n require(value <= type(uint120).max, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n return uint120(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint112 from uint256, reverting on\\n * overflow (when the input is greater than largest uint112).\\n *\\n * Counterpart to Solidity's `uint112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint112(uint256 value) internal pure returns (uint112) {\\n require(value <= type(uint112).max, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n return uint112(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint104 from uint256, reverting on\\n * overflow (when the input is greater than largest uint104).\\n *\\n * Counterpart to Solidity's `uint104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint104(uint256 value) internal pure returns (uint104) {\\n require(value <= type(uint104).max, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n return uint104(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.2._\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint88 from uint256, reverting on\\n * overflow (when the input is greater than largest uint88).\\n *\\n * Counterpart to Solidity's `uint88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint88(uint256 value) internal pure returns (uint88) {\\n require(value <= type(uint88).max, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n return uint88(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint80 from uint256, reverting on\\n * overflow (when the input is greater than largest uint80).\\n *\\n * Counterpart to Solidity's `uint80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint80(uint256 value) internal pure returns (uint80) {\\n require(value <= type(uint80).max, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n return uint80(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint72 from uint256, reverting on\\n * overflow (when the input is greater than largest uint72).\\n *\\n * Counterpart to Solidity's `uint72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint72(uint256 value) internal pure returns (uint72) {\\n require(value <= type(uint72).max, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n return uint72(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint56 from uint256, reverting on\\n * overflow (when the input is greater than largest uint56).\\n *\\n * Counterpart to Solidity's `uint56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint56(uint256 value) internal pure returns (uint56) {\\n require(value <= type(uint56).max, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n return uint56(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint48 from uint256, reverting on\\n * overflow (when the input is greater than largest uint48).\\n *\\n * Counterpart to Solidity's `uint48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint48(uint256 value) internal pure returns (uint48) {\\n require(value <= type(uint48).max, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n return uint48(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint40 from uint256, reverting on\\n * overflow (when the input is greater than largest uint40).\\n *\\n * Counterpart to Solidity's `uint40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint40(uint256 value) internal pure returns (uint40) {\\n require(value <= type(uint40).max, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n return uint40(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint24 from uint256, reverting on\\n * overflow (when the input is greater than largest uint24).\\n *\\n * Counterpart to Solidity's `uint24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toUint24(uint256 value) internal pure returns (uint24) {\\n require(value <= type(uint24).max, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n return uint24(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v2.5._\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n *\\n * _Available since v3.0._\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int248 from int256, reverting on\\n * overflow (when the input is less than smallest int248 or\\n * greater than largest int248).\\n *\\n * Counterpart to Solidity's `int248` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 248 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\\n downcasted = int248(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 248 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int240 from int256, reverting on\\n * overflow (when the input is less than smallest int240 or\\n * greater than largest int240).\\n *\\n * Counterpart to Solidity's `int240` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 240 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\\n downcasted = int240(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 240 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int232 from int256, reverting on\\n * overflow (when the input is less than smallest int232 or\\n * greater than largest int232).\\n *\\n * Counterpart to Solidity's `int232` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 232 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\\n downcasted = int232(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 232 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int224 from int256, reverting on\\n * overflow (when the input is less than smallest int224 or\\n * greater than largest int224).\\n *\\n * Counterpart to Solidity's `int224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\\n downcasted = int224(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int216 from int256, reverting on\\n * overflow (when the input is less than smallest int216 or\\n * greater than largest int216).\\n *\\n * Counterpart to Solidity's `int216` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 216 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\\n downcasted = int216(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 216 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int208 from int256, reverting on\\n * overflow (when the input is less than smallest int208 or\\n * greater than largest int208).\\n *\\n * Counterpart to Solidity's `int208` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 208 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\\n downcasted = int208(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 208 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int200 from int256, reverting on\\n * overflow (when the input is less than smallest int200 or\\n * greater than largest int200).\\n *\\n * Counterpart to Solidity's `int200` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 200 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\\n downcasted = int200(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 200 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int192 from int256, reverting on\\n * overflow (when the input is less than smallest int192 or\\n * greater than largest int192).\\n *\\n * Counterpart to Solidity's `int192` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 192 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\\n downcasted = int192(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 192 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int184 from int256, reverting on\\n * overflow (when the input is less than smallest int184 or\\n * greater than largest int184).\\n *\\n * Counterpart to Solidity's `int184` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 184 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\\n downcasted = int184(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 184 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int176 from int256, reverting on\\n * overflow (when the input is less than smallest int176 or\\n * greater than largest int176).\\n *\\n * Counterpart to Solidity's `int176` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 176 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\\n downcasted = int176(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 176 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int168 from int256, reverting on\\n * overflow (when the input is less than smallest int168 or\\n * greater than largest int168).\\n *\\n * Counterpart to Solidity's `int168` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 168 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\\n downcasted = int168(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 168 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int160 from int256, reverting on\\n * overflow (when the input is less than smallest int160 or\\n * greater than largest int160).\\n *\\n * Counterpart to Solidity's `int160` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 160 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\\n downcasted = int160(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 160 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int152 from int256, reverting on\\n * overflow (when the input is less than smallest int152 or\\n * greater than largest int152).\\n *\\n * Counterpart to Solidity's `int152` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 152 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\\n downcasted = int152(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 152 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int144 from int256, reverting on\\n * overflow (when the input is less than smallest int144 or\\n * greater than largest int144).\\n *\\n * Counterpart to Solidity's `int144` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 144 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\\n downcasted = int144(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 144 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int136 from int256, reverting on\\n * overflow (when the input is less than smallest int136 or\\n * greater than largest int136).\\n *\\n * Counterpart to Solidity's `int136` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 136 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\\n downcasted = int136(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 136 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\\n downcasted = int128(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int120 from int256, reverting on\\n * overflow (when the input is less than smallest int120 or\\n * greater than largest int120).\\n *\\n * Counterpart to Solidity's `int120` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 120 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\\n downcasted = int120(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 120 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int112 from int256, reverting on\\n * overflow (when the input is less than smallest int112 or\\n * greater than largest int112).\\n *\\n * Counterpart to Solidity's `int112` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 112 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\\n downcasted = int112(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 112 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int104 from int256, reverting on\\n * overflow (when the input is less than smallest int104 or\\n * greater than largest int104).\\n *\\n * Counterpart to Solidity's `int104` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 104 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\\n downcasted = int104(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 104 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int96 from int256, reverting on\\n * overflow (when the input is less than smallest int96 or\\n * greater than largest int96).\\n *\\n * Counterpart to Solidity's `int96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\\n downcasted = int96(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int88 from int256, reverting on\\n * overflow (when the input is less than smallest int88 or\\n * greater than largest int88).\\n *\\n * Counterpart to Solidity's `int88` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 88 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\\n downcasted = int88(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 88 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int80 from int256, reverting on\\n * overflow (when the input is less than smallest int80 or\\n * greater than largest int80).\\n *\\n * Counterpart to Solidity's `int80` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 80 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\\n downcasted = int80(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 80 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int72 from int256, reverting on\\n * overflow (when the input is less than smallest int72 or\\n * greater than largest int72).\\n *\\n * Counterpart to Solidity's `int72` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 72 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\\n downcasted = int72(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 72 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\\n downcasted = int64(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int56 from int256, reverting on\\n * overflow (when the input is less than smallest int56 or\\n * greater than largest int56).\\n *\\n * Counterpart to Solidity's `int56` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 56 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\\n downcasted = int56(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 56 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int48 from int256, reverting on\\n * overflow (when the input is less than smallest int48 or\\n * greater than largest int48).\\n *\\n * Counterpart to Solidity's `int48` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 48 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\\n downcasted = int48(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 48 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int40 from int256, reverting on\\n * overflow (when the input is less than smallest int40 or\\n * greater than largest int40).\\n *\\n * Counterpart to Solidity's `int40` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 40 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\\n downcasted = int40(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 40 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\\n downcasted = int32(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int24 from int256, reverting on\\n * overflow (when the input is less than smallest int24 or\\n * greater than largest int24).\\n *\\n * Counterpart to Solidity's `int24` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 24 bits\\n *\\n * _Available since v4.7._\\n */\\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\\n downcasted = int24(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 24 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\\n downcasted = int16(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\\n downcasted = int8(value);\\n require(downcasted == value, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n *\\n * _Available since v3.0._\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x52a8cfb0f5239d11b457dcdd1b326992ef672714ca8da71a157255bddd13f3ad\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// CAUTION\\n// This version of SafeMath should only be used with Solidity 0.8 or later,\\n// because it relies on the compiler's built in overflow checks.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations.\\n *\\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\\n * now has built in overflow checking.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator.\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0f633a0223d9a1dcccfcf38a64c9de0874dfcbfac0c6941ccf074d63a2ce0e1e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc3ff3f5c4584e1d9a483ad7ced51ab64523201f4e3d3c65293e4ca8aeb77a961\",\"license\":\"MIT\"},\"contracts/EAS/TellerAS.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\nimport \\\"../Types.sol\\\";\\nimport \\\"../interfaces/IEAS.sol\\\";\\nimport \\\"../interfaces/IASRegistry.sol\\\";\\n\\n/**\\n * @title TellerAS - Teller Attestation Service - based on EAS - Ethereum Attestation Service\\n */\\ncontract TellerAS is IEAS {\\n error AccessDenied();\\n error AlreadyRevoked();\\n error InvalidAttestation();\\n error InvalidExpirationTime();\\n error InvalidOffset();\\n error InvalidRegistry();\\n error InvalidSchema();\\n error InvalidVerifier();\\n error NotFound();\\n error NotPayable();\\n\\n string public constant VERSION = \\\"0.8\\\";\\n\\n // A terminator used when concatenating and hashing multiple fields.\\n string private constant HASH_TERMINATOR = \\\"@\\\";\\n\\n // The AS global registry.\\n IASRegistry private immutable _asRegistry;\\n\\n // The EIP712 verifier used to verify signed attestations.\\n IEASEIP712Verifier private immutable _eip712Verifier;\\n\\n // A mapping between attestations and their related attestations.\\n mapping(bytes32 => bytes32[]) private _relatedAttestations;\\n\\n // A mapping between an account and its received attestations.\\n mapping(address => mapping(bytes32 => bytes32[]))\\n private _receivedAttestations;\\n\\n // A mapping between an account and its sent attestations.\\n mapping(address => mapping(bytes32 => bytes32[])) private _sentAttestations;\\n\\n // A mapping between a schema and its attestations.\\n mapping(bytes32 => bytes32[]) private _schemaAttestations;\\n\\n // The global mapping between attestations and their UUIDs.\\n mapping(bytes32 => Attestation) private _db;\\n\\n // The global counter for the total number of attestations.\\n uint256 private _attestationsCount;\\n\\n bytes32 private _lastUUID;\\n\\n /**\\n * @dev Creates a new EAS instance.\\n *\\n * @param registry The address of the global AS registry.\\n * @param verifier The address of the EIP712 verifier.\\n */\\n constructor(IASRegistry registry, IEASEIP712Verifier verifier) {\\n if (address(registry) == address(0x0)) {\\n revert InvalidRegistry();\\n }\\n\\n if (address(verifier) == address(0x0)) {\\n revert InvalidVerifier();\\n }\\n\\n _asRegistry = registry;\\n _eip712Verifier = verifier;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getASRegistry() external view override returns (IASRegistry) {\\n return _asRegistry;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getEIP712Verifier()\\n external\\n view\\n override\\n returns (IEASEIP712Verifier)\\n {\\n return _eip712Verifier;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getAttestationsCount() external view override returns (uint256) {\\n return _attestationsCount;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function attest(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data\\n ) public payable virtual override returns (bytes32) {\\n return\\n _attest(\\n recipient,\\n schema,\\n expirationTime,\\n refUUID,\\n data,\\n msg.sender\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function attestByDelegation(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public payable virtual override returns (bytes32) {\\n _eip712Verifier.attest(\\n recipient,\\n schema,\\n expirationTime,\\n refUUID,\\n data,\\n attester,\\n v,\\n r,\\n s\\n );\\n\\n return\\n _attest(recipient, schema, expirationTime, refUUID, data, attester);\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function revoke(bytes32 uuid) public virtual override {\\n return _revoke(uuid, msg.sender);\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function revokeByDelegation(\\n bytes32 uuid,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) public virtual override {\\n _eip712Verifier.revoke(uuid, attester, v, r, s);\\n\\n _revoke(uuid, attester);\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getAttestation(bytes32 uuid)\\n external\\n view\\n override\\n returns (Attestation memory)\\n {\\n return _db[uuid];\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function isAttestationValid(bytes32 uuid)\\n public\\n view\\n override\\n returns (bool)\\n {\\n return _db[uuid].uuid != 0;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function isAttestationActive(bytes32 uuid)\\n public\\n view\\n virtual\\n override\\n returns (bool)\\n {\\n return\\n isAttestationValid(uuid) &&\\n _db[uuid].expirationTime >= block.timestamp &&\\n _db[uuid].revocationTime == 0;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getReceivedAttestationUUIDs(\\n address recipient,\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view override returns (bytes32[] memory) {\\n return\\n _sliceUUIDs(\\n _receivedAttestations[recipient][schema],\\n start,\\n length,\\n reverseOrder\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getReceivedAttestationUUIDsCount(address recipient, bytes32 schema)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n return _receivedAttestations[recipient][schema].length;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getSentAttestationUUIDs(\\n address attester,\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view override returns (bytes32[] memory) {\\n return\\n _sliceUUIDs(\\n _sentAttestations[attester][schema],\\n start,\\n length,\\n reverseOrder\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getSentAttestationUUIDsCount(address recipient, bytes32 schema)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n return _sentAttestations[recipient][schema].length;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getRelatedAttestationUUIDs(\\n bytes32 uuid,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view override returns (bytes32[] memory) {\\n return\\n _sliceUUIDs(\\n _relatedAttestations[uuid],\\n start,\\n length,\\n reverseOrder\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getRelatedAttestationUUIDsCount(bytes32 uuid)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n return _relatedAttestations[uuid].length;\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getSchemaAttestationUUIDs(\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view override returns (bytes32[] memory) {\\n return\\n _sliceUUIDs(\\n _schemaAttestations[schema],\\n start,\\n length,\\n reverseOrder\\n );\\n }\\n\\n /**\\n * @inheritdoc IEAS\\n */\\n function getSchemaAttestationUUIDsCount(bytes32 schema)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n return _schemaAttestations[schema].length;\\n }\\n\\n /**\\n * @dev Attests to a specific AS.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param expirationTime The expiration time of the attestation.\\n * @param refUUID An optional related attestation's UUID.\\n * @param data Additional custom data.\\n * @param attester The attesting account.\\n *\\n * @return The UUID of the new attestation.\\n */\\n function _attest(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data,\\n address attester\\n ) private returns (bytes32) {\\n if (expirationTime <= block.timestamp) {\\n revert InvalidExpirationTime();\\n }\\n\\n IASRegistry.ASRecord memory asRecord = _asRegistry.getAS(schema);\\n if (asRecord.uuid == EMPTY_UUID) {\\n revert InvalidSchema();\\n }\\n\\n IASResolver resolver = asRecord.resolver;\\n if (address(resolver) != address(0x0)) {\\n if (msg.value != 0 && !resolver.isPayable()) {\\n revert NotPayable();\\n }\\n\\n if (\\n !resolver.resolve{ value: msg.value }(\\n recipient,\\n asRecord.schema,\\n data,\\n expirationTime,\\n attester\\n )\\n ) {\\n revert InvalidAttestation();\\n }\\n }\\n\\n Attestation memory attestation = Attestation({\\n uuid: EMPTY_UUID,\\n schema: schema,\\n recipient: recipient,\\n attester: attester,\\n time: block.timestamp,\\n expirationTime: expirationTime,\\n revocationTime: 0,\\n refUUID: refUUID,\\n data: data\\n });\\n\\n _lastUUID = _getUUID(attestation);\\n attestation.uuid = _lastUUID;\\n\\n _receivedAttestations[recipient][schema].push(_lastUUID);\\n _sentAttestations[attester][schema].push(_lastUUID);\\n _schemaAttestations[schema].push(_lastUUID);\\n\\n _db[_lastUUID] = attestation;\\n _attestationsCount++;\\n\\n if (refUUID != 0) {\\n if (!isAttestationValid(refUUID)) {\\n revert NotFound();\\n }\\n\\n _relatedAttestations[refUUID].push(_lastUUID);\\n }\\n\\n emit Attested(recipient, attester, _lastUUID, schema);\\n\\n return _lastUUID;\\n }\\n\\n function getLastUUID() external view returns (bytes32) {\\n return _lastUUID;\\n }\\n\\n /**\\n * @dev Revokes an existing attestation to a specific AS.\\n *\\n * @param uuid The UUID of the attestation to revoke.\\n * @param attester The attesting account.\\n */\\n function _revoke(bytes32 uuid, address attester) private {\\n Attestation storage attestation = _db[uuid];\\n if (attestation.uuid == EMPTY_UUID) {\\n revert NotFound();\\n }\\n\\n if (attestation.attester != attester) {\\n revert AccessDenied();\\n }\\n\\n if (attestation.revocationTime != 0) {\\n revert AlreadyRevoked();\\n }\\n\\n attestation.revocationTime = block.timestamp;\\n\\n emit Revoked(attestation.recipient, attester, uuid, attestation.schema);\\n }\\n\\n /**\\n * @dev Calculates a UUID for a given attestation.\\n *\\n * @param attestation The input attestation.\\n *\\n * @return Attestation UUID.\\n */\\n function _getUUID(Attestation memory attestation)\\n private\\n view\\n returns (bytes32)\\n {\\n return\\n keccak256(\\n abi.encodePacked(\\n attestation.schema,\\n attestation.recipient,\\n attestation.attester,\\n attestation.time,\\n attestation.expirationTime,\\n attestation.data,\\n HASH_TERMINATOR,\\n _attestationsCount\\n )\\n );\\n }\\n\\n /**\\n * @dev Returns a slice in an array of attestation UUIDs.\\n *\\n * @param uuids The array of attestation UUIDs.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function _sliceUUIDs(\\n bytes32[] memory uuids,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) private pure returns (bytes32[] memory) {\\n uint256 attestationsLength = uuids.length;\\n if (attestationsLength == 0) {\\n return new bytes32[](0);\\n }\\n\\n if (start >= attestationsLength) {\\n revert InvalidOffset();\\n }\\n\\n uint256 len = length;\\n if (attestationsLength < start + length) {\\n len = attestationsLength - start;\\n }\\n\\n bytes32[] memory res = new bytes32[](len);\\n\\n for (uint256 i = 0; i < len; ++i) {\\n res[i] = uuids[\\n reverseOrder ? attestationsLength - (start + i + 1) : start + i\\n ];\\n }\\n\\n return res;\\n }\\n}\\n\",\"keccak256\":\"0x5a41ca49530d1b4697b5ea58b02900a3297b42a84e49c2753a55b5939c84a415\",\"license\":\"MIT\"},\"contracts/TellerV2Storage.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\nimport { IMarketRegistry } from \\\"./interfaces/IMarketRegistry.sol\\\";\\nimport \\\"./interfaces/IEscrowVault.sol\\\";\\nimport \\\"./interfaces/IReputationManager.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./interfaces/ICollateralManager.sol\\\";\\nimport { PaymentType, PaymentCycleType } from \\\"./libraries/V2Calculations.sol\\\";\\nimport \\\"./interfaces/ILenderManager.sol\\\";\\n\\nenum BidState {\\n NONEXISTENT,\\n PENDING,\\n CANCELLED,\\n ACCEPTED,\\n PAID,\\n LIQUIDATED,\\n CLOSED\\n}\\n\\n/**\\n * @notice Represents a total amount for a payment.\\n * @param principal Amount that counts towards the principal.\\n * @param interest Amount that counts toward interest.\\n */\\nstruct Payment {\\n uint256 principal;\\n uint256 interest;\\n}\\n\\n/**\\n * @notice Details about a loan request.\\n * @param borrower Account address who is requesting a loan.\\n * @param receiver Account address who will receive the loan amount.\\n * @param lender Account address who accepted and funded the loan request.\\n * @param marketplaceId ID of the marketplace the bid was submitted to.\\n * @param metadataURI ID of off chain metadata to find additional information of the loan request.\\n * @param loanDetails Struct of the specific loan details.\\n * @param terms Struct of the loan request terms.\\n * @param state Represents the current state of the loan.\\n */\\nstruct Bid {\\n address borrower;\\n address receiver;\\n address lender; // if this is the LenderManager address, we use that .owner() as source of truth\\n uint256 marketplaceId;\\n bytes32 _metadataURI; // DEPRECATED\\n LoanDetails loanDetails;\\n Terms terms;\\n BidState state;\\n PaymentType paymentType;\\n}\\n\\n/**\\n * @notice Details about the loan.\\n * @param lendingToken The token address for the loan.\\n * @param principal The amount of tokens initially lent out.\\n * @param totalRepaid Payment struct that represents the total principal and interest amount repaid.\\n * @param timestamp Timestamp, in seconds, of when the bid was submitted by the borrower.\\n * @param acceptedTimestamp Timestamp, in seconds, of when the bid was accepted by the lender.\\n * @param lastRepaidTimestamp Timestamp, in seconds, of when the last payment was made\\n * @param loanDuration The duration of the loan.\\n */\\nstruct LoanDetails {\\n IERC20 lendingToken;\\n uint256 principal;\\n Payment totalRepaid;\\n uint32 timestamp;\\n uint32 acceptedTimestamp;\\n uint32 lastRepaidTimestamp;\\n uint32 loanDuration;\\n}\\n\\n/**\\n * @notice Information on the terms of a loan request\\n * @param paymentCycleAmount Value of tokens expected to be repaid every payment cycle.\\n * @param paymentCycle Duration, in seconds, of how often a payment must be made.\\n * @param APR Annual percentage rating to be applied on repayments. (10000 == 100%)\\n */\\nstruct Terms {\\n uint256 paymentCycleAmount;\\n uint32 paymentCycle;\\n uint16 APR;\\n}\\n\\nabstract contract TellerV2Storage_G0 {\\n /** Storage Variables */\\n\\n // Current number of bids.\\n uint256 public bidId;\\n\\n // Mapping of bidId to bid information.\\n mapping(uint256 => Bid) public bids;\\n\\n // Mapping of borrowers to borrower requests.\\n mapping(address => uint256[]) public borrowerBids;\\n\\n // Mapping of volume filled by lenders.\\n mapping(address => uint256) public __lenderVolumeFilled; // DEPRECIATED\\n\\n // Volume filled by all lenders.\\n uint256 public __totalVolumeFilled; // DEPRECIATED\\n\\n // List of allowed lending tokens\\n EnumerableSet.AddressSet internal __lendingTokensSet; // DEPRECATED\\n\\n IMarketRegistry public marketRegistry;\\n IReputationManager public reputationManager;\\n\\n // Mapping of borrowers to borrower requests.\\n mapping(address => EnumerableSet.UintSet) internal _borrowerBidsActive;\\n\\n mapping(uint256 => uint32) public bidDefaultDuration;\\n mapping(uint256 => uint32) public bidExpirationTime;\\n\\n // Mapping of volume filled by lenders.\\n // Asset address => Lender address => Volume amount\\n mapping(address => mapping(address => uint256)) public lenderVolumeFilled;\\n\\n // Volume filled by all lenders.\\n // Asset address => Volume amount\\n mapping(address => uint256) public totalVolumeFilled;\\n\\n uint256 public version;\\n\\n // Mapping of metadataURIs by bidIds.\\n // Bid Id => metadataURI string\\n mapping(uint256 => string) public uris;\\n}\\n\\nabstract contract TellerV2Storage_G1 is TellerV2Storage_G0 {\\n // market ID => trusted forwarder\\n mapping(uint256 => address) internal _trustedMarketForwarders;\\n // trusted forwarder => set of pre-approved senders\\n mapping(address => EnumerableSet.AddressSet)\\n internal _approvedForwarderSenders;\\n}\\n\\nabstract contract TellerV2Storage_G2 is TellerV2Storage_G1 {\\n address public lenderCommitmentForwarder;\\n}\\n\\nabstract contract TellerV2Storage_G3 is TellerV2Storage_G2 {\\n ICollateralManager public collateralManager;\\n}\\n\\nabstract contract TellerV2Storage_G4 is TellerV2Storage_G3 {\\n // Address of the lender manager contract\\n ILenderManager public lenderManager;\\n // BidId to payment cycle type (custom or monthly)\\n mapping(uint256 => PaymentCycleType) public bidPaymentCycleType;\\n}\\n\\nabstract contract TellerV2Storage_G5 is TellerV2Storage_G4 {\\n // Address of the lender manager contract\\n IEscrowVault public escrowVault;\\n}\\n\\nabstract contract TellerV2Storage_G6 is TellerV2Storage_G5 {\\n mapping(uint256 => address) public repaymentListenerForBid;\\n}\\n\\nabstract contract TellerV2Storage_G7 is TellerV2Storage_G6 {\\n mapping(address => bool) private __pauserRoleBearer ;//pauserRoleBearer;\\n bool private __liquidationsPaused; //liquidations paused\\n}\\n\\nabstract contract TellerV2Storage is TellerV2Storage_G7 {}\\n\",\"keccak256\":\"0x8443c1195c03e75e0a7cf48df02818f0c253e1f62ce8c2492595c1db9559e7f1\",\"license\":\"MIT\"},\"contracts/Types.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\n// A representation of an empty/uninitialized UUID.\\nbytes32 constant EMPTY_UUID = 0;\\n\",\"keccak256\":\"0x2e4bcf4a965f840193af8729251386c1826cd050411ba4a9e85984a2551fd2ff\",\"license\":\"MIT\"},\"contracts/interfaces/IASRegistry.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\nimport \\\"./IASResolver.sol\\\";\\n\\n/**\\n * @title The global AS registry interface.\\n */\\ninterface IASRegistry {\\n /**\\n * @title A struct representing a record for a submitted AS (Attestation Schema).\\n */\\n struct ASRecord {\\n // A unique identifier of the AS.\\n bytes32 uuid;\\n // Optional schema resolver.\\n IASResolver resolver;\\n // Auto-incrementing index for reference, assigned by the registry itself.\\n uint256 index;\\n // Custom specification of the AS (e.g., an ABI).\\n bytes schema;\\n }\\n\\n /**\\n * @dev Triggered when a new AS has been registered\\n *\\n * @param uuid The AS UUID.\\n * @param index The AS index.\\n * @param schema The AS schema.\\n * @param resolver An optional AS schema resolver.\\n * @param attester The address of the account used to register the AS.\\n */\\n event Registered(\\n bytes32 indexed uuid,\\n uint256 indexed index,\\n bytes schema,\\n IASResolver resolver,\\n address attester\\n );\\n\\n /**\\n * @dev Submits and reserve a new AS\\n *\\n * @param schema The AS data schema.\\n * @param resolver An optional AS schema resolver.\\n *\\n * @return The UUID of the new AS.\\n */\\n function register(bytes calldata schema, IASResolver resolver)\\n external\\n returns (bytes32);\\n\\n /**\\n * @dev Returns an existing AS by UUID\\n *\\n * @param uuid The UUID of the AS to retrieve.\\n *\\n * @return The AS data members.\\n */\\n function getAS(bytes32 uuid) external view returns (ASRecord memory);\\n\\n /**\\n * @dev Returns the global counter for the total number of attestations\\n *\\n * @return The global counter for the total number of attestations.\\n */\\n function getASCount() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x74752921f592df45c8717d7084627e823b1dbc93bad7187cd3023c9690df7e60\",\"license\":\"MIT\"},\"contracts/interfaces/IASResolver.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n\\n// SPDX-License-Identifier: MIT\\n\\n/**\\n * @title The interface of an optional AS resolver.\\n */\\ninterface IASResolver {\\n /**\\n * @dev Returns whether the resolver supports ETH transfers\\n */\\n function isPayable() external pure returns (bool);\\n\\n /**\\n * @dev Resolves an attestation and verifier whether its data conforms to the spec.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The AS data schema.\\n * @param data The actual attestation data.\\n * @param expirationTime The expiration time of the attestation.\\n * @param msgSender The sender of the original attestation message.\\n *\\n * @return Whether the data is valid according to the scheme.\\n */\\n function resolve(\\n address recipient,\\n bytes calldata schema,\\n bytes calldata data,\\n uint256 expirationTime,\\n address msgSender\\n ) external payable returns (bool);\\n}\\n\",\"keccak256\":\"0xfce671ea099d9f997a69c3447eb4a9c9693d37c5b97e43ada376e614e1c7cb61\",\"license\":\"MIT\"},\"contracts/interfaces/ICollateralManager.sol\":{\"content\":\"// SPDX-Licence-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\n\\nimport { Collateral } from \\\"./escrow/ICollateralEscrowV1.sol\\\";\\n\\ninterface ICollateralManager {\\n /**\\n * @notice Checks the validity of a borrower's collateral balance.\\n * @param _bidId The id of the associated bid.\\n * @param _collateralInfo Additional information about the collateral asset.\\n * @return validation_ Boolean indicating if the collateral balance was validated.\\n */\\n function commitCollateral(\\n uint256 _bidId,\\n Collateral[] calldata _collateralInfo\\n ) external returns (bool validation_);\\n\\n /**\\n * @notice Checks the validity of a borrower's collateral balance and commits it to a bid.\\n * @param _bidId The id of the associated bid.\\n * @param _collateralInfo Additional information about the collateral asset.\\n * @return validation_ Boolean indicating if the collateral balance was validated.\\n */\\n function commitCollateral(\\n uint256 _bidId,\\n Collateral calldata _collateralInfo\\n ) external returns (bool validation_);\\n\\n function checkBalances(\\n address _borrowerAddress,\\n Collateral[] calldata _collateralInfo\\n ) external returns (bool validated_, bool[] memory checks_);\\n\\n /**\\n * @notice Deploys a new collateral escrow.\\n * @param _bidId The associated bidId of the collateral escrow.\\n */\\n function deployAndDeposit(uint256 _bidId) external;\\n\\n /**\\n * @notice Gets the address of a deployed escrow.\\n * @notice _bidId The bidId to return the escrow for.\\n * @return The address of the escrow.\\n */\\n function getEscrow(uint256 _bidId) external view returns (address);\\n\\n /**\\n * @notice Gets the collateral info for a given bid id.\\n * @param _bidId The bidId to return the collateral info for.\\n * @return The stored collateral info.\\n */\\n function getCollateralInfo(uint256 _bidId)\\n external\\n view\\n returns (Collateral[] memory);\\n\\n function getCollateralAmount(uint256 _bidId, address collateralAssetAddress)\\n external\\n view\\n returns (uint256 _amount);\\n\\n /**\\n * @notice Withdraws deposited collateral from the created escrow of a bid.\\n * @param _bidId The id of the bid to withdraw collateral for.\\n */\\n function withdraw(uint256 _bidId) external;\\n\\n /**\\n * @notice Re-checks the validity of a borrower's collateral balance committed to a bid.\\n * @param _bidId The id of the associated bid.\\n * @return validation_ Boolean indicating if the collateral balance was validated.\\n */\\n function revalidateCollateral(uint256 _bidId) external returns (bool);\\n\\n /**\\n * @notice Sends the deposited collateral to a lender of a bid.\\n * @notice Can only be called by the protocol.\\n * @param _bidId The id of the liquidated bid.\\n */\\n function lenderClaimCollateral(uint256 _bidId) external;\\n\\n\\n\\n /**\\n * @notice Sends the deposited collateral to a lender of a bid.\\n * @notice Can only be called by the protocol.\\n * @param _bidId The id of the liquidated bid.\\n * @param _collateralRecipient the address that will receive the collateral \\n */\\n function lenderClaimCollateralWithRecipient(uint256 _bidId, address _collateralRecipient) external;\\n\\n\\n /**\\n * @notice Sends the deposited collateral to a liquidator of a bid.\\n * @notice Can only be called by the protocol.\\n * @param _bidId The id of the liquidated bid.\\n * @param _liquidatorAddress The address of the liquidator to send the collateral to.\\n */\\n function liquidateCollateral(uint256 _bidId, address _liquidatorAddress)\\n external;\\n}\\n\",\"keccak256\":\"0x58734812c9549a2d53d86ac6349b2fba615460732145e863ef9d0c8dc3712d08\"},\"contracts/interfaces/IEAS.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n// SPDX-License-Identifier: MIT\\n\\nimport \\\"./IASRegistry.sol\\\";\\nimport \\\"./IEASEIP712Verifier.sol\\\";\\n\\n/**\\n * @title EAS - Ethereum Attestation Service interface\\n */\\ninterface IEAS {\\n /**\\n * @dev A struct representing a single attestation.\\n */\\n struct Attestation {\\n // A unique identifier of the attestation.\\n bytes32 uuid;\\n // A unique identifier of the AS.\\n bytes32 schema;\\n // The recipient of the attestation.\\n address recipient;\\n // The attester/sender of the attestation.\\n address attester;\\n // The time when the attestation was created (Unix timestamp).\\n uint256 time;\\n // The time when the attestation expires (Unix timestamp).\\n uint256 expirationTime;\\n // The time when the attestation was revoked (Unix timestamp).\\n uint256 revocationTime;\\n // The UUID of the related attestation.\\n bytes32 refUUID;\\n // Custom attestation data.\\n bytes data;\\n }\\n\\n /**\\n * @dev Triggered when an attestation has been made.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param attester The attesting account.\\n * @param uuid The UUID the revoked attestation.\\n * @param schema The UUID of the AS.\\n */\\n event Attested(\\n address indexed recipient,\\n address indexed attester,\\n bytes32 uuid,\\n bytes32 indexed schema\\n );\\n\\n /**\\n * @dev Triggered when an attestation has been revoked.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param attester The attesting account.\\n * @param schema The UUID of the AS.\\n * @param uuid The UUID the revoked attestation.\\n */\\n event Revoked(\\n address indexed recipient,\\n address indexed attester,\\n bytes32 uuid,\\n bytes32 indexed schema\\n );\\n\\n /**\\n * @dev Returns the address of the AS global registry.\\n *\\n * @return The address of the AS global registry.\\n */\\n function getASRegistry() external view returns (IASRegistry);\\n\\n /**\\n * @dev Returns the address of the EIP712 verifier used to verify signed attestations.\\n *\\n * @return The address of the EIP712 verifier used to verify signed attestations.\\n */\\n function getEIP712Verifier() external view returns (IEASEIP712Verifier);\\n\\n /**\\n * @dev Returns the global counter for the total number of attestations.\\n *\\n * @return The global counter for the total number of attestations.\\n */\\n function getAttestationsCount() external view returns (uint256);\\n\\n /**\\n * @dev Attests to a specific AS.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param expirationTime The expiration time of the attestation.\\n * @param refUUID An optional related attestation's UUID.\\n * @param data Additional custom data.\\n *\\n * @return The UUID of the new attestation.\\n */\\n function attest(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data\\n ) external payable returns (bytes32);\\n\\n /**\\n * @dev Attests to a specific AS using a provided EIP712 signature.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param expirationTime The expiration time of the attestation.\\n * @param refUUID An optional related attestation's UUID.\\n * @param data Additional custom data.\\n * @param attester The attesting account.\\n * @param v The recovery ID.\\n * @param r The x-coordinate of the nonce R.\\n * @param s The signature data.\\n *\\n * @return The UUID of the new attestation.\\n */\\n function attestByDelegation(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external payable returns (bytes32);\\n\\n /**\\n * @dev Revokes an existing attestation to a specific AS.\\n *\\n * @param uuid The UUID of the attestation to revoke.\\n */\\n function revoke(bytes32 uuid) external;\\n\\n /**\\n * @dev Attests to a specific AS using a provided EIP712 signature.\\n *\\n * @param uuid The UUID of the attestation to revoke.\\n * @param attester The attesting account.\\n * @param v The recovery ID.\\n * @param r The x-coordinate of the nonce R.\\n * @param s The signature data.\\n */\\n function revokeByDelegation(\\n bytes32 uuid,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns an existing attestation by UUID.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n *\\n * @return The attestation data members.\\n */\\n function getAttestation(bytes32 uuid)\\n external\\n view\\n returns (Attestation memory);\\n\\n /**\\n * @dev Checks whether an attestation exists.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n *\\n * @return Whether an attestation exists.\\n */\\n function isAttestationValid(bytes32 uuid) external view returns (bool);\\n\\n /**\\n * @dev Checks whether an attestation is active.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n *\\n * @return Whether an attestation is active.\\n */\\n function isAttestationActive(bytes32 uuid) external view returns (bool);\\n\\n /**\\n * @dev Returns all received attestation UUIDs.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function getReceivedAttestationUUIDs(\\n address recipient,\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view returns (bytes32[] memory);\\n\\n /**\\n * @dev Returns the number of received attestation UUIDs.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n *\\n * @return The number of attestations.\\n */\\n function getReceivedAttestationUUIDsCount(address recipient, bytes32 schema)\\n external\\n view\\n returns (uint256);\\n\\n /**\\n * @dev Returns all sent attestation UUIDs.\\n *\\n * @param attester The attesting account.\\n * @param schema The UUID of the AS.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function getSentAttestationUUIDs(\\n address attester,\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view returns (bytes32[] memory);\\n\\n /**\\n * @dev Returns the number of sent attestation UUIDs.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n *\\n * @return The number of attestations.\\n */\\n function getSentAttestationUUIDsCount(address recipient, bytes32 schema)\\n external\\n view\\n returns (uint256);\\n\\n /**\\n * @dev Returns all attestations related to a specific attestation.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function getRelatedAttestationUUIDs(\\n bytes32 uuid,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view returns (bytes32[] memory);\\n\\n /**\\n * @dev Returns the number of related attestation UUIDs.\\n *\\n * @param uuid The UUID of the attestation to retrieve.\\n *\\n * @return The number of related attestations.\\n */\\n function getRelatedAttestationUUIDsCount(bytes32 uuid)\\n external\\n view\\n returns (uint256);\\n\\n /**\\n * @dev Returns all per-schema attestation UUIDs.\\n *\\n * @param schema The UUID of the AS.\\n * @param start The offset to start from.\\n * @param length The number of total members to retrieve.\\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\\n *\\n * @return An array of attestation UUIDs.\\n */\\n function getSchemaAttestationUUIDs(\\n bytes32 schema,\\n uint256 start,\\n uint256 length,\\n bool reverseOrder\\n ) external view returns (bytes32[] memory);\\n\\n /**\\n * @dev Returns the number of per-schema attestation UUIDs.\\n *\\n * @param schema The UUID of the AS.\\n *\\n * @return The number of attestations.\\n */\\n function getSchemaAttestationUUIDsCount(bytes32 schema)\\n external\\n view\\n returns (uint256);\\n}\\n\",\"keccak256\":\"0x5db90829269f806ed14a6c638f38d4aac1fa0f85829b34a2fcddd5200261c148\",\"license\":\"MIT\"},\"contracts/interfaces/IEASEIP712Verifier.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n\\n// SPDX-License-Identifier: MIT\\n\\n/**\\n * @title EIP712 typed signatures verifier for EAS delegated attestations interface.\\n */\\ninterface IEASEIP712Verifier {\\n /**\\n * @dev Returns the current nonce per-account.\\n *\\n * @param account The requested accunt.\\n *\\n * @return The current nonce.\\n */\\n function getNonce(address account) external view returns (uint256);\\n\\n /**\\n * @dev Verifies signed attestation.\\n *\\n * @param recipient The recipient of the attestation.\\n * @param schema The UUID of the AS.\\n * @param expirationTime The expiration time of the attestation.\\n * @param refUUID An optional related attestation's UUID.\\n * @param data Additional custom data.\\n * @param attester The attesting account.\\n * @param v The recovery ID.\\n * @param r The x-coordinate of the nonce R.\\n * @param s The signature data.\\n */\\n function attest(\\n address recipient,\\n bytes32 schema,\\n uint256 expirationTime,\\n bytes32 refUUID,\\n bytes calldata data,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Verifies signed revocations.\\n *\\n * @param uuid The UUID of the attestation to revoke.\\n * @param attester The attesting account.\\n * @param v The recovery ID.\\n * @param r The x-coordinate of the nonce R.\\n * @param s The signature data.\\n */\\n function revoke(\\n bytes32 uuid,\\n address attester,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0xeca3ac3bacec52af15b2c86c5bf1a1be315aade51fa86f95da2b426b28486b1e\",\"license\":\"MIT\"},\"contracts/interfaces/IEscrowVault.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\n\\ninterface IEscrowVault {\\n /**\\n * @notice Deposit tokens on behalf of another account\\n * @param account The address of the account\\n * @param token The address of the token\\n * @param amount The amount to increase the balance\\n */\\n function deposit(address account, address token, uint256 amount) external;\\n\\n function withdraw(address token, uint256 amount) external ;\\n}\\n\",\"keccak256\":\"0x7d80ce49d143f2f509e1992ed41200e07376bea48950e3674db71a343882f2c8\",\"license\":\"MIT\"},\"contracts/interfaces/ILenderManager.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n\\n// SPDX-License-Identifier: MIT\\nimport \\\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\\\";\\n\\nabstract contract ILenderManager is IERC721Upgradeable {\\n /**\\n * @notice Registers a new active lender for a loan, minting the nft.\\n * @param _bidId The id for the loan to set.\\n * @param _newLender The address of the new active lender.\\n */\\n function registerLoan(uint256 _bidId, address _newLender) external virtual;\\n}\\n\",\"keccak256\":\"0xceb1ea2ef4c6e2ad7986db84de49c959e8d59844563d27daca5b8d78b732a8f7\",\"license\":\"MIT\"},\"contracts/interfaces/IMarketRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"../EAS/TellerAS.sol\\\";\\nimport { PaymentType, PaymentCycleType } from \\\"../libraries/V2Calculations.sol\\\";\\n\\ninterface IMarketRegistry {\\n function initialize(TellerAS tellerAs) external;\\n\\n function isVerifiedLender(uint256 _marketId, address _lender)\\n external\\n view\\n returns (bool, bytes32);\\n\\n function isMarketOpen(uint256 _marketId) external view returns (bool);\\n\\n function isMarketClosed(uint256 _marketId) external view returns (bool);\\n\\n function isVerifiedBorrower(uint256 _marketId, address _borrower)\\n external\\n view\\n returns (bool, bytes32);\\n\\n function getMarketOwner(uint256 _marketId) external view returns (address);\\n\\n function getMarketFeeRecipient(uint256 _marketId)\\n external\\n view\\n returns (address);\\n\\n function getMarketURI(uint256 _marketId)\\n external\\n view\\n returns (string memory);\\n\\n function getPaymentCycle(uint256 _marketId)\\n external\\n view\\n returns (uint32, PaymentCycleType);\\n\\n function getPaymentDefaultDuration(uint256 _marketId)\\n external\\n view\\n returns (uint32);\\n\\n function getBidExpirationTime(uint256 _marketId)\\n external\\n view\\n returns (uint32);\\n\\n function getMarketplaceFee(uint256 _marketId)\\n external\\n view\\n returns (uint16);\\n\\n function getPaymentType(uint256 _marketId)\\n external\\n view\\n returns (PaymentType);\\n\\n function createMarket(\\n address _initialOwner,\\n uint32 _paymentCycleDuration,\\n uint32 _paymentDefaultDuration,\\n uint32 _bidExpirationTime,\\n uint16 _feePercent,\\n bool _requireLenderAttestation,\\n bool _requireBorrowerAttestation,\\n PaymentType _paymentType,\\n PaymentCycleType _paymentCycleType,\\n string calldata _uri\\n ) external returns (uint256 marketId_);\\n\\n function createMarket(\\n address _initialOwner,\\n uint32 _paymentCycleDuration,\\n uint32 _paymentDefaultDuration,\\n uint32 _bidExpirationTime,\\n uint16 _feePercent,\\n bool _requireLenderAttestation,\\n bool _requireBorrowerAttestation,\\n string calldata _uri\\n ) external returns (uint256 marketId_);\\n\\n function closeMarket(uint256 _marketId) external;\\n}\\n\",\"keccak256\":\"0x2a17561a47cb3517f2820d68d9bbcd86dcd21c59cad7208581004ecd91d5478a\",\"license\":\"MIT\"},\"contracts/interfaces/IReputationManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum RepMark {\\n Good,\\n Delinquent,\\n Default\\n}\\n\\ninterface IReputationManager {\\n function initialize(address protocolAddress) external;\\n\\n function getDelinquentLoanIds(address _account)\\n external\\n returns (uint256[] memory);\\n\\n function getDefaultedLoanIds(address _account)\\n external\\n returns (uint256[] memory);\\n\\n function getCurrentDelinquentLoanIds(address _account)\\n external\\n returns (uint256[] memory);\\n\\n function getCurrentDefaultLoanIds(address _account)\\n external\\n returns (uint256[] memory);\\n\\n function updateAccountReputation(address _account) external;\\n\\n function updateAccountReputation(address _account, uint256 _bidId)\\n external\\n returns (RepMark);\\n}\\n\",\"keccak256\":\"0x8d6e50fd460912231e53135b4459aa2f6f16007ae8deb32bc2cee1e88311a8d8\",\"license\":\"MIT\"},\"contracts/interfaces/escrow/ICollateralEscrowV1.sol\":{\"content\":\"// SPDX-Licence-Identifier: MIT\\npragma solidity >=0.8.0 <0.9.0;\\n\\nenum CollateralType {\\n ERC20,\\n ERC721,\\n ERC1155\\n}\\n\\nstruct Collateral {\\n CollateralType _collateralType;\\n uint256 _amount;\\n uint256 _tokenId;\\n address _collateralAddress;\\n}\\n\\ninterface ICollateralEscrowV1 {\\n /**\\n * @notice Deposits a collateral asset into the escrow.\\n * @param _collateralType The type of collateral asset to deposit (ERC721, ERC1155).\\n * @param _collateralAddress The address of the collateral token.i feel\\n * @param _amount The amount to deposit.\\n */\\n function depositAsset(\\n CollateralType _collateralType,\\n address _collateralAddress,\\n uint256 _amount,\\n uint256 _tokenId\\n ) external payable;\\n\\n /**\\n * @notice Withdraws a collateral asset from the escrow.\\n * @param _collateralAddress The address of the collateral contract.\\n * @param _amount The amount to withdraw.\\n * @param _recipient The address to send the assets to.\\n */\\n function withdraw(\\n address _collateralAddress,\\n uint256 _amount,\\n address _recipient\\n ) external;\\n\\n function withdrawDustTokens( \\n address _tokenAddress, \\n uint256 _amount,\\n address _recipient\\n ) external;\\n\\n\\n function getBid() external view returns (uint256);\\n\\n function initialize(uint256 _bidId) external;\\n\\n\\n}\\n\",\"keccak256\":\"0xc5b554eea7e17e47acc632cab40894bac2d2699864fdccc61e08fa8f546c0437\"},\"contracts/libraries/DateTimeLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >=0.6.0 <0.9.0;\\n\\n// ----------------------------------------------------------------------------\\n// BokkyPooBah's DateTime Library v1.01\\n//\\n// A gas-efficient Solidity date and time library\\n//\\n// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\\n//\\n// Tested date range 1970/01/01 to 2345/12/31\\n//\\n// Conventions:\\n// Unit | Range | Notes\\n// :-------- |:-------------:|:-----\\n// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC\\n// year | 1970 ... 2345 |\\n// month | 1 ... 12 |\\n// day | 1 ... 31 |\\n// hour | 0 ... 23 |\\n// minute | 0 ... 59 |\\n// second | 0 ... 59 |\\n// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday\\n//\\n//\\n// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.\\n// ----------------------------------------------------------------------------\\n\\nlibrary BokkyPooBahsDateTimeLibrary {\\n uint constant SECONDS_PER_DAY = 24 * 60 * 60;\\n uint constant SECONDS_PER_HOUR = 60 * 60;\\n uint constant SECONDS_PER_MINUTE = 60;\\n int constant OFFSET19700101 = 2440588;\\n\\n uint constant DOW_MON = 1;\\n uint constant DOW_TUE = 2;\\n uint constant DOW_WED = 3;\\n uint constant DOW_THU = 4;\\n uint constant DOW_FRI = 5;\\n uint constant DOW_SAT = 6;\\n uint constant DOW_SUN = 7;\\n\\n // ------------------------------------------------------------------------\\n // Calculate the number of days from 1970/01/01 to year/month/day using\\n // the date conversion algorithm from\\n // https://aa.usno.navy.mil/faq/JD_formula.html\\n // and subtracting the offset 2440588 so that 1970/01/01 is day 0\\n //\\n // days = day\\n // - 32075\\n // + 1461 * (year + 4800 + (month - 14) / 12) / 4\\n // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12\\n // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4\\n // - offset\\n // ------------------------------------------------------------------------\\n function _daysFromDate(uint year, uint month, uint day)\\n internal\\n pure\\n returns (uint _days)\\n {\\n require(year >= 1970);\\n int _year = int(year);\\n int _month = int(month);\\n int _day = int(day);\\n\\n int __days = _day -\\n 32075 +\\n (1461 * (_year + 4800 + (_month - 14) / 12)) /\\n 4 +\\n (367 * (_month - 2 - ((_month - 14) / 12) * 12)) /\\n 12 -\\n (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /\\n 4 -\\n OFFSET19700101;\\n\\n _days = uint(__days);\\n }\\n\\n // ------------------------------------------------------------------------\\n // Calculate year/month/day from the number of days since 1970/01/01 using\\n // the date conversion algorithm from\\n // http://aa.usno.navy.mil/faq/docs/JD_Formula.php\\n // and adding the offset 2440588 so that 1970/01/01 is day 0\\n //\\n // int L = days + 68569 + offset\\n // int N = 4 * L / 146097\\n // L = L - (146097 * N + 3) / 4\\n // year = 4000 * (L + 1) / 1461001\\n // L = L - 1461 * year / 4 + 31\\n // month = 80 * L / 2447\\n // dd = L - 2447 * month / 80\\n // L = month / 11\\n // month = month + 2 - 12 * L\\n // year = 100 * (N - 49) + year + L\\n // ------------------------------------------------------------------------\\n function _daysToDate(uint _days)\\n internal\\n pure\\n returns (uint year, uint month, uint day)\\n {\\n int __days = int(_days);\\n\\n int L = __days + 68569 + OFFSET19700101;\\n int N = (4 * L) / 146097;\\n L = L - (146097 * N + 3) / 4;\\n int _year = (4000 * (L + 1)) / 1461001;\\n L = L - (1461 * _year) / 4 + 31;\\n int _month = (80 * L) / 2447;\\n int _day = L - (2447 * _month) / 80;\\n L = _month / 11;\\n _month = _month + 2 - 12 * L;\\n _year = 100 * (N - 49) + _year + L;\\n\\n year = uint(_year);\\n month = uint(_month);\\n day = uint(_day);\\n }\\n\\n function timestampFromDate(uint year, uint month, uint day)\\n internal\\n pure\\n returns (uint timestamp)\\n {\\n timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;\\n }\\n\\n function timestampFromDateTime(\\n uint year,\\n uint month,\\n uint day,\\n uint hour,\\n uint minute,\\n uint second\\n ) internal pure returns (uint timestamp) {\\n timestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n hour *\\n SECONDS_PER_HOUR +\\n minute *\\n SECONDS_PER_MINUTE +\\n second;\\n }\\n\\n function timestampToDate(uint timestamp)\\n internal\\n pure\\n returns (uint year, uint month, uint day)\\n {\\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n }\\n\\n function timestampToDateTime(uint timestamp)\\n internal\\n pure\\n returns (\\n uint year,\\n uint month,\\n uint day,\\n uint hour,\\n uint minute,\\n uint second\\n )\\n {\\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n uint secs = timestamp % SECONDS_PER_DAY;\\n hour = secs / SECONDS_PER_HOUR;\\n secs = secs % SECONDS_PER_HOUR;\\n minute = secs / SECONDS_PER_MINUTE;\\n second = secs % SECONDS_PER_MINUTE;\\n }\\n\\n function isValidDate(uint year, uint month, uint day)\\n internal\\n pure\\n returns (bool valid)\\n {\\n if (year >= 1970 && month > 0 && month <= 12) {\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > 0 && day <= daysInMonth) {\\n valid = true;\\n }\\n }\\n }\\n\\n function isValidDateTime(\\n uint year,\\n uint month,\\n uint day,\\n uint hour,\\n uint minute,\\n uint second\\n ) internal pure returns (bool valid) {\\n if (isValidDate(year, month, day)) {\\n if (hour < 24 && minute < 60 && second < 60) {\\n valid = true;\\n }\\n }\\n }\\n\\n function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {\\n (uint year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n leapYear = _isLeapYear(year);\\n }\\n\\n function _isLeapYear(uint year) internal pure returns (bool leapYear) {\\n leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);\\n }\\n\\n function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {\\n weekDay = getDayOfWeek(timestamp) <= DOW_FRI;\\n }\\n\\n function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {\\n weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;\\n }\\n\\n function getDaysInMonth(uint timestamp)\\n internal\\n pure\\n returns (uint daysInMonth)\\n {\\n (uint year, uint month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n daysInMonth = _getDaysInMonth(year, month);\\n }\\n\\n function _getDaysInMonth(uint year, uint month)\\n internal\\n pure\\n returns (uint daysInMonth)\\n {\\n if (\\n month == 1 ||\\n month == 3 ||\\n month == 5 ||\\n month == 7 ||\\n month == 8 ||\\n month == 10 ||\\n month == 12\\n ) {\\n daysInMonth = 31;\\n } else if (month != 2) {\\n daysInMonth = 30;\\n } else {\\n daysInMonth = _isLeapYear(year) ? 29 : 28;\\n }\\n }\\n\\n // 1 = Monday, 7 = Sunday\\n function getDayOfWeek(uint timestamp)\\n internal\\n pure\\n returns (uint dayOfWeek)\\n {\\n uint _days = timestamp / SECONDS_PER_DAY;\\n dayOfWeek = ((_days + 3) % 7) + 1;\\n }\\n\\n function getYear(uint timestamp) internal pure returns (uint year) {\\n (year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n }\\n\\n function getMonth(uint timestamp) internal pure returns (uint month) {\\n (, month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n }\\n\\n function getDay(uint timestamp) internal pure returns (uint day) {\\n (, , day) = _daysToDate(timestamp / SECONDS_PER_DAY);\\n }\\n\\n function getHour(uint timestamp) internal pure returns (uint hour) {\\n uint secs = timestamp % SECONDS_PER_DAY;\\n hour = secs / SECONDS_PER_HOUR;\\n }\\n\\n function getMinute(uint timestamp) internal pure returns (uint minute) {\\n uint secs = timestamp % SECONDS_PER_HOUR;\\n minute = secs / SECONDS_PER_MINUTE;\\n }\\n\\n function getSecond(uint timestamp) internal pure returns (uint second) {\\n second = timestamp % SECONDS_PER_MINUTE;\\n }\\n\\n function addYears(uint timestamp, uint _years)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n (uint year, uint month, uint day) = _daysToDate(\\n timestamp / SECONDS_PER_DAY\\n );\\n year += _years;\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > daysInMonth) {\\n day = daysInMonth;\\n }\\n newTimestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n (timestamp % SECONDS_PER_DAY);\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addMonths(uint timestamp, uint _months)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n (uint year, uint month, uint day) = _daysToDate(\\n timestamp / SECONDS_PER_DAY\\n );\\n month += _months;\\n year += (month - 1) / 12;\\n month = ((month - 1) % 12) + 1;\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > daysInMonth) {\\n day = daysInMonth;\\n }\\n newTimestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n (timestamp % SECONDS_PER_DAY);\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addDays(uint timestamp, uint _days)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp + _days * SECONDS_PER_DAY;\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addHours(uint timestamp, uint _hours)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addMinutes(uint timestamp, uint _minutes)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;\\n require(newTimestamp >= timestamp);\\n }\\n\\n function addSeconds(uint timestamp, uint _seconds)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp + _seconds;\\n require(newTimestamp >= timestamp);\\n }\\n\\n function subYears(uint timestamp, uint _years)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n (uint year, uint month, uint day) = _daysToDate(\\n timestamp / SECONDS_PER_DAY\\n );\\n year -= _years;\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > daysInMonth) {\\n day = daysInMonth;\\n }\\n newTimestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n (timestamp % SECONDS_PER_DAY);\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subMonths(uint timestamp, uint _months)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n (uint year, uint month, uint day) = _daysToDate(\\n timestamp / SECONDS_PER_DAY\\n );\\n uint yearMonth = year * 12 + (month - 1) - _months;\\n year = yearMonth / 12;\\n month = (yearMonth % 12) + 1;\\n uint daysInMonth = _getDaysInMonth(year, month);\\n if (day > daysInMonth) {\\n day = daysInMonth;\\n }\\n newTimestamp =\\n _daysFromDate(year, month, day) *\\n SECONDS_PER_DAY +\\n (timestamp % SECONDS_PER_DAY);\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subDays(uint timestamp, uint _days)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp - _days * SECONDS_PER_DAY;\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subHours(uint timestamp, uint _hours)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subMinutes(uint timestamp, uint _minutes)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;\\n require(newTimestamp <= timestamp);\\n }\\n\\n function subSeconds(uint timestamp, uint _seconds)\\n internal\\n pure\\n returns (uint newTimestamp)\\n {\\n newTimestamp = timestamp - _seconds;\\n require(newTimestamp <= timestamp);\\n }\\n\\n function diffYears(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _years)\\n {\\n require(fromTimestamp <= toTimestamp);\\n (uint fromYear, , ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\\n (uint toYear, , ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\\n _years = toYear - fromYear;\\n }\\n\\n function diffMonths(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _months)\\n {\\n require(fromTimestamp <= toTimestamp);\\n (uint fromYear, uint fromMonth, ) = _daysToDate(\\n fromTimestamp / SECONDS_PER_DAY\\n );\\n (uint toYear, uint toMonth, ) = _daysToDate(\\n toTimestamp / SECONDS_PER_DAY\\n );\\n _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;\\n }\\n\\n function diffDays(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _days)\\n {\\n require(fromTimestamp <= toTimestamp);\\n _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;\\n }\\n\\n function diffHours(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _hours)\\n {\\n require(fromTimestamp <= toTimestamp);\\n _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;\\n }\\n\\n function diffMinutes(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _minutes)\\n {\\n require(fromTimestamp <= toTimestamp);\\n _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;\\n }\\n\\n function diffSeconds(uint fromTimestamp, uint toTimestamp)\\n internal\\n pure\\n returns (uint _seconds)\\n {\\n require(fromTimestamp <= toTimestamp);\\n _seconds = toTimestamp - fromTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0xf194df8ea9946a5bb3300223629b7e4959c1f20bacba27b3dc5f6dd2a160147a\",\"license\":\"MIT\"},\"contracts/libraries/NumbersLib.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n// Libraries\\nimport { SafeCast } from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport { Math } from \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"./WadRayMath.sol\\\";\\n\\n/**\\n * @dev Utility library for uint256 numbers\\n *\\n * @author develop@teller.finance\\n */\\nlibrary NumbersLib {\\n using WadRayMath for uint256;\\n\\n /**\\n * @dev It represents 100% with 2 decimal places.\\n */\\n uint16 internal constant PCT_100 = 10000;\\n\\n function percentFactor(uint256 decimals) internal pure returns (uint256) {\\n return 100 * (10**decimals);\\n }\\n\\n /**\\n * @notice Returns a percentage value of a number.\\n * @param self The number to get a percentage of.\\n * @param percentage The percentage value to calculate with 2 decimal places (10000 = 100%).\\n */\\n function percent(uint256 self, uint16 percentage)\\n internal\\n pure\\n returns (uint256)\\n {\\n return percent(self, percentage, 2);\\n }\\n\\n /**\\n * @notice Returns a percentage value of a number.\\n * @param self The number to get a percentage of.\\n * @param percentage The percentage value to calculate with.\\n * @param decimals The number of decimals the percentage value is in.\\n */\\n function percent(uint256 self, uint256 percentage, uint256 decimals)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (self * percentage) / percentFactor(decimals);\\n }\\n\\n /**\\n * @notice it returns the absolute number of a specified parameter\\n * @param self the number to be returned in it's absolute\\n * @return the absolute number\\n */\\n function abs(int256 self) internal pure returns (uint256) {\\n return self >= 0 ? uint256(self) : uint256(-1 * self);\\n }\\n\\n /**\\n * @notice Returns a ratio percentage of {num1} to {num2}.\\n * @dev Returned value is type uint16.\\n * @param num1 The number used to get the ratio for.\\n * @param num2 The number used to get the ratio from.\\n * @return Ratio percentage with 2 decimal places (10000 = 100%).\\n */\\n function ratioOf(uint256 num1, uint256 num2)\\n internal\\n pure\\n returns (uint16)\\n {\\n return SafeCast.toUint16(ratioOf(num1, num2, 2));\\n }\\n\\n /**\\n * @notice Returns a ratio percentage of {num1} to {num2}.\\n * @param num1 The number used to get the ratio for.\\n * @param num2 The number used to get the ratio from.\\n * @param decimals The number of decimals the percentage value is returned in.\\n * @return Ratio percentage value.\\n */\\n function ratioOf(uint256 num1, uint256 num2, uint256 decimals)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (num2 == 0) return 0;\\n return (num1 * percentFactor(decimals)) / num2;\\n }\\n\\n /**\\n * @notice Calculates the payment amount for a cycle duration.\\n * The formula is calculated based on the standard Estimated Monthly Installment (https://en.wikipedia.org/wiki/Equated_monthly_installment)\\n * EMI = [P x R x (1+R)^N]/[(1+R)^N-1]\\n * @param principal The starting amount that is owed on the loan.\\n * @param loanDuration The length of the loan.\\n * @param cycleDuration The length of the loan's payment cycle.\\n * @param apr The annual percentage rate of the loan.\\n */\\n function pmt(\\n uint256 principal,\\n uint32 loanDuration,\\n uint32 cycleDuration,\\n uint16 apr,\\n uint256 daysInYear\\n ) internal pure returns (uint256) {\\n require(\\n loanDuration >= cycleDuration,\\n \\\"PMT: cycle duration < loan duration\\\"\\n );\\n if (apr == 0)\\n return\\n Math.mulDiv(\\n principal,\\n cycleDuration,\\n loanDuration,\\n Math.Rounding.Up\\n );\\n\\n // Number of payment cycles for the duration of the loan\\n uint256 n = Math.ceilDiv(loanDuration, cycleDuration);\\n\\n uint256 one = WadRayMath.wad();\\n uint256 r = WadRayMath.pctToWad(apr).wadMul(cycleDuration).wadDiv(\\n daysInYear\\n );\\n uint256 exp = (one + r).wadPow(n);\\n uint256 numerator = principal.wadMul(r).wadMul(exp);\\n uint256 denominator = exp - one;\\n\\n return numerator.wadDiv(denominator);\\n }\\n}\\n\",\"keccak256\":\"0x78009ffb3737ab7615a1e38a26635d6c06b65b7b7959af46d6ef840d220e70cf\",\"license\":\"MIT\"},\"contracts/libraries/V2Calculations.sol\":{\"content\":\"pragma solidity >=0.8.0 <0.9.0;\\n\\n// SPDX-License-Identifier: MIT\\n\\n// Libraries\\nimport \\\"./NumbersLib.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport { Bid } from \\\"../TellerV2Storage.sol\\\";\\nimport { BokkyPooBahsDateTimeLibrary as BPBDTL } from \\\"./DateTimeLib.sol\\\";\\n\\nenum PaymentType {\\n EMI,\\n Bullet\\n}\\n\\nenum PaymentCycleType {\\n Seconds,\\n Monthly\\n}\\n\\nlibrary V2Calculations {\\n using NumbersLib for uint256;\\n\\n /**\\n * @notice Returns the timestamp of the last payment made for a loan.\\n * @param _bid The loan bid struct to get the timestamp for.\\n */\\n function lastRepaidTimestamp(Bid storage _bid)\\n internal\\n view\\n returns (uint32)\\n {\\n return\\n _bid.loanDetails.lastRepaidTimestamp == 0\\n ? _bid.loanDetails.acceptedTimestamp\\n : _bid.loanDetails.lastRepaidTimestamp;\\n }\\n\\n /**\\n * @notice Calculates the amount owed for a loan.\\n * @param _bid The loan bid struct to get the owed amount for.\\n * @param _timestamp The timestamp at which to get the owed amount at.\\n * @param _paymentCycleType The payment cycle type of the loan (Seconds or Monthly).\\n */\\n function calculateAmountOwed(\\n Bid storage _bid,\\n uint256 _timestamp,\\n PaymentCycleType _paymentCycleType,\\n uint32 _paymentCycleDuration\\n )\\n public\\n view\\n returns (\\n uint256 owedPrincipal_,\\n uint256 duePrincipal_,\\n uint256 interest_\\n )\\n {\\n // Total principal left to pay\\n return\\n calculateAmountOwed(\\n _bid,\\n lastRepaidTimestamp(_bid),\\n _timestamp,\\n _paymentCycleType,\\n _paymentCycleDuration\\n );\\n }\\n\\n function calculateAmountOwed(\\n Bid storage _bid,\\n uint256 _lastRepaidTimestamp,\\n uint256 _timestamp,\\n PaymentCycleType _paymentCycleType,\\n uint32 _paymentCycleDuration\\n )\\n public\\n view\\n returns (\\n uint256 owedPrincipal_,\\n uint256 duePrincipal_,\\n uint256 interest_\\n )\\n {\\n owedPrincipal_ =\\n _bid.loanDetails.principal -\\n _bid.loanDetails.totalRepaid.principal;\\n\\n uint256 owedTime = _timestamp - uint256(_lastRepaidTimestamp);\\n\\n {\\n uint256 daysInYear = _paymentCycleType == PaymentCycleType.Monthly\\n ? 360 days\\n : 365 days;\\n\\n uint256 interestOwedInAYear = owedPrincipal_.percent(_bid.terms.APR, 2);\\n \\n interest_ = (interestOwedInAYear * owedTime) / daysInYear;\\n }\\n\\n\\n bool isLastPaymentCycle;\\n {\\n uint256 lastPaymentCycleDuration = _bid.loanDetails.loanDuration %\\n _paymentCycleDuration;\\n if (lastPaymentCycleDuration == 0) {\\n lastPaymentCycleDuration = _paymentCycleDuration;\\n }\\n\\n uint256 endDate = uint256(_bid.loanDetails.acceptedTimestamp) +\\n uint256(_bid.loanDetails.loanDuration);\\n uint256 lastPaymentCycleStart = endDate -\\n uint256(lastPaymentCycleDuration);\\n\\n isLastPaymentCycle =\\n uint256(_timestamp) > lastPaymentCycleStart ||\\n owedPrincipal_ + interest_ <= _bid.terms.paymentCycleAmount;\\n }\\n\\n if (_bid.paymentType == PaymentType.Bullet) {\\n if (isLastPaymentCycle) {\\n duePrincipal_ = owedPrincipal_;\\n }\\n } else {\\n // Default to PaymentType.EMI\\n // Max payable amount in a cycle\\n // NOTE: the last cycle could have less than the calculated payment amount\\n\\n //the amount owed for the cycle should never exceed the current payment cycle amount so we use min here \\n uint256 owedAmountForCycle = Math.min( ((_bid.terms.paymentCycleAmount * owedTime) ) /\\n _paymentCycleDuration , _bid.terms.paymentCycleAmount+interest_ ) ;\\n\\n uint256 owedAmount = isLastPaymentCycle\\n ? owedPrincipal_ + interest_\\n : owedAmountForCycle ;\\n\\n duePrincipal_ = Math.min(owedAmount - interest_, owedPrincipal_);\\n }\\n }\\n\\n /**\\n * @notice Calculates the amount owed for a loan for the next payment cycle.\\n * @param _type The payment type of the loan.\\n * @param _cycleType The cycle type set for the loan. (Seconds or Monthly)\\n * @param _principal The starting amount that is owed on the loan.\\n * @param _duration The length of the loan.\\n * @param _paymentCycle The length of the loan's payment cycle.\\n * @param _apr The annual percentage rate of the loan.\\n */\\n function calculatePaymentCycleAmount(\\n PaymentType _type,\\n PaymentCycleType _cycleType,\\n uint256 _principal,\\n uint32 _duration,\\n uint32 _paymentCycle,\\n uint16 _apr\\n ) public view returns (uint256) {\\n uint256 daysInYear = _cycleType == PaymentCycleType.Monthly\\n ? 360 days\\n : 365 days;\\n if (_type == PaymentType.Bullet) {\\n return\\n _principal.percent(_apr).percent(\\n uint256(_paymentCycle).ratioOf(daysInYear, 10),\\n 10\\n );\\n }\\n // Default to PaymentType.EMI\\n return\\n NumbersLib.pmt(\\n _principal,\\n _duration,\\n _paymentCycle,\\n _apr,\\n daysInYear\\n );\\n }\\n\\n function calculateNextDueDate(\\n uint32 _acceptedTimestamp,\\n uint32 _paymentCycle,\\n uint32 _loanDuration,\\n uint32 _lastRepaidTimestamp,\\n PaymentCycleType _bidPaymentCycleType\\n ) public view returns (uint32 dueDate_) {\\n // Calculate due date if payment cycle is set to monthly\\n if (_bidPaymentCycleType == PaymentCycleType.Monthly) {\\n // Calculate the cycle number the last repayment was made\\n uint256 lastPaymentCycle = BPBDTL.diffMonths(\\n _acceptedTimestamp,\\n _lastRepaidTimestamp\\n );\\n if (\\n BPBDTL.getDay(_lastRepaidTimestamp) >\\n BPBDTL.getDay(_acceptedTimestamp)\\n ) {\\n lastPaymentCycle += 2;\\n } else {\\n lastPaymentCycle += 1;\\n }\\n\\n dueDate_ = uint32(\\n BPBDTL.addMonths(_acceptedTimestamp, lastPaymentCycle)\\n );\\n } else if (_bidPaymentCycleType == PaymentCycleType.Seconds) {\\n // Start with the original due date being 1 payment cycle since bid was accepted\\n dueDate_ = _acceptedTimestamp + _paymentCycle;\\n // Calculate the cycle number the last repayment was made\\n uint32 delta = _lastRepaidTimestamp - _acceptedTimestamp;\\n if (delta > 0) {\\n uint32 repaymentCycle = uint32(\\n Math.ceilDiv(delta, _paymentCycle)\\n );\\n dueDate_ += (repaymentCycle * _paymentCycle);\\n }\\n }\\n\\n uint32 endOfLoan = _acceptedTimestamp + _loanDuration;\\n //if we are in the last payment cycle, the next due date is the end of loan duration\\n if (dueDate_ > endOfLoan) {\\n dueDate_ = endOfLoan;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x8452535763bfb5c529a0089b8b669d77cc4e1e333b526b89b5d42ab491fb4312\",\"license\":\"MIT\"},\"contracts/libraries/WadRayMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\n/**\\n * @title WadRayMath library\\n * @author Multiplier Finance\\n * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits)\\n */\\nlibrary WadRayMath {\\n using SafeMath for uint256;\\n\\n uint256 internal constant WAD = 1e18;\\n uint256 internal constant halfWAD = WAD / 2;\\n\\n uint256 internal constant RAY = 1e27;\\n uint256 internal constant halfRAY = RAY / 2;\\n\\n uint256 internal constant WAD_RAY_RATIO = 1e9;\\n uint256 internal constant PCT_WAD_RATIO = 1e14;\\n uint256 internal constant PCT_RAY_RATIO = 1e23;\\n\\n function ray() internal pure returns (uint256) {\\n return RAY;\\n }\\n\\n function wad() internal pure returns (uint256) {\\n return WAD;\\n }\\n\\n function halfRay() internal pure returns (uint256) {\\n return halfRAY;\\n }\\n\\n function halfWad() internal pure returns (uint256) {\\n return halfWAD;\\n }\\n\\n function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return halfWAD.add(a.mul(b)).div(WAD);\\n }\\n\\n function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 halfB = b / 2;\\n\\n return halfB.add(a.mul(WAD)).div(b);\\n }\\n\\n function rayMul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return halfRAY.add(a.mul(b)).div(RAY);\\n }\\n\\n function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 halfB = b / 2;\\n\\n return halfB.add(a.mul(RAY)).div(b);\\n }\\n\\n function rayToWad(uint256 a) internal pure returns (uint256) {\\n uint256 halfRatio = WAD_RAY_RATIO / 2;\\n\\n return halfRatio.add(a).div(WAD_RAY_RATIO);\\n }\\n\\n function rayToPct(uint256 a) internal pure returns (uint16) {\\n uint256 halfRatio = PCT_RAY_RATIO / 2;\\n\\n uint256 val = halfRatio.add(a).div(PCT_RAY_RATIO);\\n return SafeCast.toUint16(val);\\n }\\n\\n function wadToPct(uint256 a) internal pure returns (uint16) {\\n uint256 halfRatio = PCT_WAD_RATIO / 2;\\n\\n uint256 val = halfRatio.add(a).div(PCT_WAD_RATIO);\\n return SafeCast.toUint16(val);\\n }\\n\\n function wadToRay(uint256 a) internal pure returns (uint256) {\\n return a.mul(WAD_RAY_RATIO);\\n }\\n\\n function pctToRay(uint16 a) internal pure returns (uint256) {\\n return uint256(a).mul(RAY).div(1e4);\\n }\\n\\n function pctToWad(uint16 a) internal pure returns (uint256) {\\n return uint256(a).mul(WAD).div(1e4);\\n }\\n\\n /**\\n * @dev calculates base^duration. The code uses the ModExp precompile\\n * @return z base^duration, in ray\\n */\\n function rayPow(uint256 x, uint256 n) internal pure returns (uint256) {\\n return _pow(x, n, RAY, rayMul);\\n }\\n\\n function wadPow(uint256 x, uint256 n) internal pure returns (uint256) {\\n return _pow(x, n, WAD, wadMul);\\n }\\n\\n function _pow(\\n uint256 x,\\n uint256 n,\\n uint256 p,\\n function(uint256, uint256) internal pure returns (uint256) mul\\n ) internal pure returns (uint256 z) {\\n z = n % 2 != 0 ? x : p;\\n\\n for (n /= 2; n != 0; n /= 2) {\\n x = mul(x, x);\\n\\n if (n % 2 != 0) {\\n z = mul(z, x);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x2781319be7a96f56966c601c061849fa94dbf9af5ad80a20c40b879a8d03f14a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61139261003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100555760003560e01c80628945b51461005a5780630dcf1658146100805780635ab17296146100a8578063e4de10d3146100d6575b600080fd5b61006d610068366004610e66565b6100e9565b6040519081526020015b60405180910390f35b61009361008e366004610ee2565b610187565b60405163ffffffff9091168152602001610077565b6100bb6100b6366004610f4b565b6102bd565b60408051938452602084019290925290820152606001610077565b6100bb6100e4366004610f9d565b6104a8565b600080600187600181111561010057610100610fe5565b1461010f576301e13380610115565b6301da9c005b63ffffffff169050600188600181111561013157610131610fe5565b141561016c5761016461015163ffffffff808716908490600a906104d816565b600a61015d898761050f565b919061052a565b91505061017d565b610179868686868561053f565b9150505b9695505050505050565b6000600182600181111561019d5761019d610fe5565b14156102195760006101bb8763ffffffff168563ffffffff16610674565b90506101cc8763ffffffff166106fb565b6101db8563ffffffff166106fb565b11156101f3576101ec600282611011565b9050610201565b6101fe600182611011565b90505b6102118763ffffffff1682610715565b91505061028d565b600082600181111561022d5761022d610fe5565b141561028d5761023d8587611029565b9050600061024b8785611051565b905063ffffffff81161561028b5760006102718263ffffffff168863ffffffff166107e7565b905061027d8782611076565b6102879084611029565b9250505b505b60006102998588611029565b90508063ffffffff168263ffffffff1611156102b3578091505b5095945050505050565b60078501546006860154600091829182916102d7916110a2565b925060006102e588886110a2565b9050600060018760018111156102fd576102fd610fe5565b1461030c576301e13380610312565b6301da9c005b600b8b015463ffffffff918216925060009161034191889164010000000090910461ffff169060029061052a16565b90508161034e84836110b9565b61035891906110ee565b60098c01549094506000925082915061037f908890600160601b900463ffffffff16611102565b63ffffffff16905080610395575063ffffffff86165b60098b01546000906103be9063ffffffff600160601b8204811691640100000000900416611011565b905060006103cc83836110a2565b9050808b11806103e95750600a8d01546103e6878a611011565b11155b9350600192506103f7915050565b600c8b0154610100900460ff16600181111561041557610415610fe5565b141561042a578015610425578493505b61049b565b60006104688763ffffffff16848d600a016000015461044991906110b9565b61045391906110ee565b600a8d0154610463908790611011565b61081e565b90506000826104775781610481565b6104818588611011565b905061049661049086836110a2565b8861081e565b955050505b5050955095509592505050565b60008060006104c8876104ba89610834565b63ffffffff168888886102bd565b9250925092509450945094915050565b6000826104e757506000610508565b826104f18361087b565b6104fb90866110b9565b61050591906110ee565b90505b9392505050565b6000610521838361ffff16600261052a565b90505b92915050565b60006105358261087b565b6104fb84866110b9565b60008363ffffffff168563ffffffff1610156105ad5760405162461bcd60e51b815260206004820152602360248201527f504d543a206379636c65206475726174696f6e203c206c6f616e20647572617460448201526234b7b760e91b606482015260840160405180910390fd5b61ffff83166105d6576105cf868563ffffffff168763ffffffff166001610893565b905061066b565b60006105ee8663ffffffff168663ffffffff166107e7565b9050670de0b6b3a7640000600061061e8561061863ffffffff8a166106128a6108e4565b90610908565b9061093c565b90506000610636846106308486611011565b9061096c565b90506000610648826106128d86610908565b9050600061065685846110a2565b9050610662828261093c565b96505050505050505b95945050505050565b60008183111561068357600080fd5b60008061069b61069662015180876110ee565b610984565b5090925090506000806106b461069662015180886110ee565b509092509050826106c685600c6110b9565b826106d285600c6110b9565b6106dc9190611011565b6106e691906110a2565b6106f091906110a2565b979650505050505050565b600061070d61069662015180846110ee565b949350505050565b600080808061072a61069662015180886110ee565b9194509250905061073b8583611011565b9150600c61074a6001846110a2565b61075491906110ee565b61075e9084611011565b9250600c61076d6001846110a2565b6107779190611125565b610782906001611011565b915060006107908484610af8565b90508082111561079e578091505b6107ab6201518088611125565b620151806107ba868686610b7e565b6107c491906110b9565b6107ce9190611011565b9450868510156107dd57600080fd5b5050505092915050565b6000821561081557816107fb6001856110a2565b61080591906110ee565b610810906001611011565b610521565b50600092915050565b600081831061082d5781610521565b5090919050565b6009810154600090600160401b900463ffffffff1615610865576009820154600160401b900463ffffffff16610524565b5060090154640100000000900463ffffffff1690565b600061088882600a61121d565b6105249060646110b9565b6000806108a1868686610cbb565b905060018360028111156108b7576108b7610fe5565b1480156108d45750600084806108cf576108cf6110d8565b868809115b1561066b5761017d600182611011565b600061052461271061090261ffff8516670de0b6b3a7640000610d6b565b90610d77565b6000610521670de0b6b3a76400006109026109238686610d6b565b6109366002670de0b6b3a76400006110ee565b90610d83565b60008061094a6002846110ee565b905061070d8361090261096587670de0b6b3a7640000610d6b565b8490610d83565b60006105218383670de0b6b3a7640000610908610d8f565b60008080838162253d8c61099b8362010bd9611229565b6109a59190611229565b9050600062023ab16109b883600461126a565b6109c291906112ef565b905060046109d38262023ab161126a565b6109de906003611229565b6109e891906112ef565b6109f2908361131d565b9150600062164b09610a05846001611229565b610a1190610fa061126a565b610a1b91906112ef565b90506004610a2b826105b561126a565b610a3591906112ef565b610a3f908461131d565b610a4a90601f611229565b9250600061098f610a5c85605061126a565b610a6691906112ef565b905060006050610a788361098f61126a565b610a8291906112ef565b610a8c908661131d565b9050610a99600b836112ef565b9450610aa685600c61126a565b610ab1836002611229565b610abb919061131d565b91508483610aca60318761131d565b610ad590606461126a565b610adf9190611229565b610ae99190611229565b9a919950975095505050505050565b60008160011480610b095750816003145b80610b145750816005145b80610b1f5750816007145b80610b2a5750816008145b80610b35575081600a145b80610b40575081600c145b15610b4d5750601f610524565b81600214610b5d5750601e610524565b610b6683610e01565b610b7157601c610b74565b601d5b60ff169392505050565b60006107b2841015610b8f57600080fd5b838383600062253d8c60046064600c610ba9600e8861131d565b610bb391906112ef565b610bbf88611324611229565b610bc99190611229565b610bd391906112ef565b610bde90600361126a565b610be891906112ef565b600c80610bf6600e8861131d565b610c0091906112ef565b610c0b90600c61126a565b610c1660028861131d565b610c20919061131d565b610c2c9061016f61126a565b610c3691906112ef565b6004600c610c45600e8961131d565b610c4f91906112ef565b610c5b896112c0611229565b610c659190611229565b610c71906105b561126a565b610c7b91906112ef565b610c87617d4b8761131d565b610c919190611229565b610c9b9190611229565b610ca5919061131d565b610caf919061131d565b98975050505050505050565b600080806000198587098587029250828110838203039150508060001415610cf657838281610cec57610cec6110d8565b0492505050610508565b808411610d0257600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600061052182846110b9565b600061052182846110ee565b60006105218284611011565b6000610d9c600285611125565b610da65782610da8565b845b9050610db56002856110ee565b93505b831561070d57610dcc85868463ffffffff16565b9450610dd9600285611125565b15610def57610dec81868463ffffffff16565b90505b610dfa6002856110ee565b9350610db8565b6000610e0e600483611125565b158015610e245750610e21606483611125565b15155b806105245750610e3661019083611125565b1592915050565b60028110610e4a57600080fd5b50565b803563ffffffff81168114610e6157600080fd5b919050565b60008060008060008060c08789031215610e7f57600080fd5b8635610e8a81610e3d565b95506020870135610e9a81610e3d565b945060408701359350610eaf60608801610e4d565b9250610ebd60808801610e4d565b915060a087013561ffff81168114610ed457600080fd5b809150509295509295509295565b600080600080600060a08688031215610efa57600080fd5b610f0386610e4d565b9450610f1160208701610e4d565b9350610f1f60408701610e4d565b9250610f2d60608701610e4d565b91506080860135610f3d81610e3d565b809150509295509295909350565b600080600080600060a08688031215610f6357600080fd5b8535945060208601359350604086013592506060860135610f8381610e3d565b9150610f9160808701610e4d565b90509295509295909350565b60008060008060808587031215610fb357600080fd5b84359350602085013592506040850135610fcc81610e3d565b9150610fda60608601610e4d565b905092959194509250565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561102457611024610ffb565b500190565b600063ffffffff80831681851680830382111561104857611048610ffb565b01949350505050565b600063ffffffff8381169083168181101561106e5761106e610ffb565b039392505050565b600063ffffffff8083168185168183048111821515161561109957611099610ffb565b02949350505050565b6000828210156110b4576110b4610ffb565b500390565b60008160001904831182151516156110d3576110d3610ffb565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826110fd576110fd6110d8565b500490565b600063ffffffff80841680611119576111196110d8565b92169190910692915050565b600082611134576111346110d8565b500690565b600181815b8085111561117457816000190482111561115a5761115a610ffb565b8085161561116757918102915b93841c939080029061113e565b509250929050565b60008261118b57506001610524565b8161119857506000610524565b81600181146111ae57600281146111b8576111d4565b6001915050610524565b60ff8411156111c9576111c9610ffb565b50506001821b610524565b5060208310610133831016604e8410600b84101617156111f7575081810a610524565b6112018383611139565b806000190482111561121557611215610ffb565b029392505050565b6000610521838361117c565b600080821280156001600160ff1b038490038513161561124b5761124b610ffb565b600160ff1b839003841281161561126457611264610ffb565b50500190565b60006001600160ff1b038184138284138082168684048611161561129057611290610ffb565b600160ff1b60008712828116878305891216156112af576112af610ffb565b600087129250878205871284841616156112cb576112cb610ffb565b878505871281841616156112e1576112e1610ffb565b505050929093029392505050565b6000826112fe576112fe6110d8565b600160ff1b82146000198414161561131857611318610ffb565b500590565b60008083128015600160ff1b85018412161561133b5761133b610ffb565b6001600160ff1b038401831381161561135657611356610ffb565b5050039056fea2646970667358221220e56a12603d33f50e7ef1cebda13db87cc1c2e3eb2ffc4064fb70019c51d8627264736f6c63430008090033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100555760003560e01c80628945b51461005a5780630dcf1658146100805780635ab17296146100a8578063e4de10d3146100d6575b600080fd5b61006d610068366004610e66565b6100e9565b6040519081526020015b60405180910390f35b61009361008e366004610ee2565b610187565b60405163ffffffff9091168152602001610077565b6100bb6100b6366004610f4b565b6102bd565b60408051938452602084019290925290820152606001610077565b6100bb6100e4366004610f9d565b6104a8565b600080600187600181111561010057610100610fe5565b1461010f576301e13380610115565b6301da9c005b63ffffffff169050600188600181111561013157610131610fe5565b141561016c5761016461015163ffffffff808716908490600a906104d816565b600a61015d898761050f565b919061052a565b91505061017d565b610179868686868561053f565b9150505b9695505050505050565b6000600182600181111561019d5761019d610fe5565b14156102195760006101bb8763ffffffff168563ffffffff16610674565b90506101cc8763ffffffff166106fb565b6101db8563ffffffff166106fb565b11156101f3576101ec600282611011565b9050610201565b6101fe600182611011565b90505b6102118763ffffffff1682610715565b91505061028d565b600082600181111561022d5761022d610fe5565b141561028d5761023d8587611029565b9050600061024b8785611051565b905063ffffffff81161561028b5760006102718263ffffffff168863ffffffff166107e7565b905061027d8782611076565b6102879084611029565b9250505b505b60006102998588611029565b90508063ffffffff168263ffffffff1611156102b3578091505b5095945050505050565b60078501546006860154600091829182916102d7916110a2565b925060006102e588886110a2565b9050600060018760018111156102fd576102fd610fe5565b1461030c576301e13380610312565b6301da9c005b600b8b015463ffffffff918216925060009161034191889164010000000090910461ffff169060029061052a16565b90508161034e84836110b9565b61035891906110ee565b60098c01549094506000925082915061037f908890600160601b900463ffffffff16611102565b63ffffffff16905080610395575063ffffffff86165b60098b01546000906103be9063ffffffff600160601b8204811691640100000000900416611011565b905060006103cc83836110a2565b9050808b11806103e95750600a8d01546103e6878a611011565b11155b9350600192506103f7915050565b600c8b0154610100900460ff16600181111561041557610415610fe5565b141561042a578015610425578493505b61049b565b60006104688763ffffffff16848d600a016000015461044991906110b9565b61045391906110ee565b600a8d0154610463908790611011565b61081e565b90506000826104775781610481565b6104818588611011565b905061049661049086836110a2565b8861081e565b955050505b5050955095509592505050565b60008060006104c8876104ba89610834565b63ffffffff168888886102bd565b9250925092509450945094915050565b6000826104e757506000610508565b826104f18361087b565b6104fb90866110b9565b61050591906110ee565b90505b9392505050565b6000610521838361ffff16600261052a565b90505b92915050565b60006105358261087b565b6104fb84866110b9565b60008363ffffffff168563ffffffff1610156105ad5760405162461bcd60e51b815260206004820152602360248201527f504d543a206379636c65206475726174696f6e203c206c6f616e20647572617460448201526234b7b760e91b606482015260840160405180910390fd5b61ffff83166105d6576105cf868563ffffffff168763ffffffff166001610893565b905061066b565b60006105ee8663ffffffff168663ffffffff166107e7565b9050670de0b6b3a7640000600061061e8561061863ffffffff8a166106128a6108e4565b90610908565b9061093c565b90506000610636846106308486611011565b9061096c565b90506000610648826106128d86610908565b9050600061065685846110a2565b9050610662828261093c565b96505050505050505b95945050505050565b60008183111561068357600080fd5b60008061069b61069662015180876110ee565b610984565b5090925090506000806106b461069662015180886110ee565b509092509050826106c685600c6110b9565b826106d285600c6110b9565b6106dc9190611011565b6106e691906110a2565b6106f091906110a2565b979650505050505050565b600061070d61069662015180846110ee565b949350505050565b600080808061072a61069662015180886110ee565b9194509250905061073b8583611011565b9150600c61074a6001846110a2565b61075491906110ee565b61075e9084611011565b9250600c61076d6001846110a2565b6107779190611125565b610782906001611011565b915060006107908484610af8565b90508082111561079e578091505b6107ab6201518088611125565b620151806107ba868686610b7e565b6107c491906110b9565b6107ce9190611011565b9450868510156107dd57600080fd5b5050505092915050565b6000821561081557816107fb6001856110a2565b61080591906110ee565b610810906001611011565b610521565b50600092915050565b600081831061082d5781610521565b5090919050565b6009810154600090600160401b900463ffffffff1615610865576009820154600160401b900463ffffffff16610524565b5060090154640100000000900463ffffffff1690565b600061088882600a61121d565b6105249060646110b9565b6000806108a1868686610cbb565b905060018360028111156108b7576108b7610fe5565b1480156108d45750600084806108cf576108cf6110d8565b868809115b1561066b5761017d600182611011565b600061052461271061090261ffff8516670de0b6b3a7640000610d6b565b90610d77565b6000610521670de0b6b3a76400006109026109238686610d6b565b6109366002670de0b6b3a76400006110ee565b90610d83565b60008061094a6002846110ee565b905061070d8361090261096587670de0b6b3a7640000610d6b565b8490610d83565b60006105218383670de0b6b3a7640000610908610d8f565b60008080838162253d8c61099b8362010bd9611229565b6109a59190611229565b9050600062023ab16109b883600461126a565b6109c291906112ef565b905060046109d38262023ab161126a565b6109de906003611229565b6109e891906112ef565b6109f2908361131d565b9150600062164b09610a05846001611229565b610a1190610fa061126a565b610a1b91906112ef565b90506004610a2b826105b561126a565b610a3591906112ef565b610a3f908461131d565b610a4a90601f611229565b9250600061098f610a5c85605061126a565b610a6691906112ef565b905060006050610a788361098f61126a565b610a8291906112ef565b610a8c908661131d565b9050610a99600b836112ef565b9450610aa685600c61126a565b610ab1836002611229565b610abb919061131d565b91508483610aca60318761131d565b610ad590606461126a565b610adf9190611229565b610ae99190611229565b9a919950975095505050505050565b60008160011480610b095750816003145b80610b145750816005145b80610b1f5750816007145b80610b2a5750816008145b80610b35575081600a145b80610b40575081600c145b15610b4d5750601f610524565b81600214610b5d5750601e610524565b610b6683610e01565b610b7157601c610b74565b601d5b60ff169392505050565b60006107b2841015610b8f57600080fd5b838383600062253d8c60046064600c610ba9600e8861131d565b610bb391906112ef565b610bbf88611324611229565b610bc99190611229565b610bd391906112ef565b610bde90600361126a565b610be891906112ef565b600c80610bf6600e8861131d565b610c0091906112ef565b610c0b90600c61126a565b610c1660028861131d565b610c20919061131d565b610c2c9061016f61126a565b610c3691906112ef565b6004600c610c45600e8961131d565b610c4f91906112ef565b610c5b896112c0611229565b610c659190611229565b610c71906105b561126a565b610c7b91906112ef565b610c87617d4b8761131d565b610c919190611229565b610c9b9190611229565b610ca5919061131d565b610caf919061131d565b98975050505050505050565b600080806000198587098587029250828110838203039150508060001415610cf657838281610cec57610cec6110d8565b0492505050610508565b808411610d0257600080fd5b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600061052182846110b9565b600061052182846110ee565b60006105218284611011565b6000610d9c600285611125565b610da65782610da8565b845b9050610db56002856110ee565b93505b831561070d57610dcc85868463ffffffff16565b9450610dd9600285611125565b15610def57610dec81868463ffffffff16565b90505b610dfa6002856110ee565b9350610db8565b6000610e0e600483611125565b158015610e245750610e21606483611125565b15155b806105245750610e3661019083611125565b1592915050565b60028110610e4a57600080fd5b50565b803563ffffffff81168114610e6157600080fd5b919050565b60008060008060008060c08789031215610e7f57600080fd5b8635610e8a81610e3d565b95506020870135610e9a81610e3d565b945060408701359350610eaf60608801610e4d565b9250610ebd60808801610e4d565b915060a087013561ffff81168114610ed457600080fd5b809150509295509295509295565b600080600080600060a08688031215610efa57600080fd5b610f0386610e4d565b9450610f1160208701610e4d565b9350610f1f60408701610e4d565b9250610f2d60608701610e4d565b91506080860135610f3d81610e3d565b809150509295509295909350565b600080600080600060a08688031215610f6357600080fd5b8535945060208601359350604086013592506060860135610f8381610e3d565b9150610f9160808701610e4d565b90509295509295909350565b60008060008060808587031215610fb357600080fd5b84359350602085013592506040850135610fcc81610e3d565b9150610fda60608601610e4d565b905092959194509250565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561102457611024610ffb565b500190565b600063ffffffff80831681851680830382111561104857611048610ffb565b01949350505050565b600063ffffffff8381169083168181101561106e5761106e610ffb565b039392505050565b600063ffffffff8083168185168183048111821515161561109957611099610ffb565b02949350505050565b6000828210156110b4576110b4610ffb565b500390565b60008160001904831182151516156110d3576110d3610ffb565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826110fd576110fd6110d8565b500490565b600063ffffffff80841680611119576111196110d8565b92169190910692915050565b600082611134576111346110d8565b500690565b600181815b8085111561117457816000190482111561115a5761115a610ffb565b8085161561116757918102915b93841c939080029061113e565b509250929050565b60008261118b57506001610524565b8161119857506000610524565b81600181146111ae57600281146111b8576111d4565b6001915050610524565b60ff8411156111c9576111c9610ffb565b50506001821b610524565b5060208310610133831016604e8410600b84101617156111f7575081810a610524565b6112018383611139565b806000190482111561121557611215610ffb565b029392505050565b6000610521838361117c565b600080821280156001600160ff1b038490038513161561124b5761124b610ffb565b600160ff1b839003841281161561126457611264610ffb565b50500190565b60006001600160ff1b038184138284138082168684048611161561129057611290610ffb565b600160ff1b60008712828116878305891216156112af576112af610ffb565b600087129250878205871284841616156112cb576112cb610ffb565b878505871281841616156112e1576112e1610ffb565b505050929093029392505050565b6000826112fe576112fe6110d8565b600160ff1b82146000198414161561131857611318610ffb565b500590565b60008083128015600160ff1b85018412161561133b5761133b610ffb565b6001600160ff1b038401831381161561135657611356610ffb565b5050039056fea2646970667358221220e56a12603d33f50e7ef1cebda13db87cc1c2e3eb2ffc4064fb70019c51d8627264736f6c63430008090033", "devdoc": { "kind": "dev", "methods": { diff --git a/packages/contracts/deployments/polygon/solcInputs/2fbfd407212128842c1766ec39678e5a.json b/packages/contracts/deployments/polygon/solcInputs/2fbfd407212128842c1766ec39678e5a.json new file mode 100644 index 000000000..b559f1672 --- /dev/null +++ b/packages/contracts/deployments/polygon/solcInputs/2fbfd407212128842c1766ec39678e5a.json @@ -0,0 +1,602 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol)\n\npragma solidity ^0.8.9;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Context variant with ERC2771 support.\n */\nabstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address private immutable _trustedForwarder;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address trustedForwarder) {\n _trustedForwarder = trustedForwarder;\n }\n\n function isTrustedForwarder(address forwarder) public view virtual returns (bool) {\n return forwarder == _trustedForwarder;\n }\n\n function _msgSender() internal view virtual override returns (address sender) {\n if (isTrustedForwarder(msg.sender)) {\n // The assembly code is more direct than the Solidity version using `abi.decode`.\n /// @solidity memory-safe-assembly\n assembly {\n sender := shr(96, calldataload(sub(calldatasize(), 20)))\n }\n } else {\n return super._msgSender();\n }\n }\n\n function _msgData() internal view virtual override returns (bytes calldata) {\n if (isTrustedForwarder(msg.sender)) {\n return msg.data[:msg.data.length - 20];\n } else {\n return super._msgData();\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/metatx/MinimalForwarderUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (metatx/MinimalForwarder.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/cryptography/ECDSAUpgradeable.sol\";\nimport \"../utils/cryptography/EIP712Upgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Simple minimal forwarder to be used together with an ERC2771 compatible contract. See {ERC2771Context}.\n *\n * MinimalForwarder is mainly meant for testing, as it is missing features to be a good production-ready forwarder. This\n * contract does not intend to have all the properties that are needed for a sound forwarding system. A fully\n * functioning forwarding system with good properties requires more complexity. We suggest you look at other projects\n * such as the GSN which do have the goal of building a system like that.\n */\ncontract MinimalForwarderUpgradeable is Initializable, EIP712Upgradeable {\n using ECDSAUpgradeable for bytes32;\n\n struct ForwardRequest {\n address from;\n address to;\n uint256 value;\n uint256 gas;\n uint256 nonce;\n bytes data;\n }\n\n bytes32 private constant _TYPEHASH =\n keccak256(\"ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data)\");\n\n mapping(address => uint256) private _nonces;\n\n function __MinimalForwarder_init() internal onlyInitializing {\n __EIP712_init_unchained(\"MinimalForwarder\", \"0.0.1\");\n }\n\n function __MinimalForwarder_init_unchained() internal onlyInitializing {}\n\n function getNonce(address from) public view returns (uint256) {\n return _nonces[from];\n }\n\n function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) {\n address signer = _hashTypedDataV4(\n keccak256(abi.encode(_TYPEHASH, req.from, req.to, req.value, req.gas, req.nonce, keccak256(req.data)))\n ).recover(signature);\n return _nonces[req.from] == req.nonce && signer == req.from;\n }\n\n function execute(ForwardRequest calldata req, bytes calldata signature)\n public\n payable\n returns (bool, bytes memory)\n {\n require(verify(req, signature), \"MinimalForwarder: signature does not match request\");\n _nonces[req.from] = req.nonce + 1;\n\n (bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(\n abi.encodePacked(req.data, req.from)\n );\n\n // Validate that the relayer has sent enough gas for the call.\n // See https://ronan.eth.limo/blog/ethereum-gas-dangers/\n if (gasleft() <= req.gas / 63) {\n // We explicitly trigger invalid opcode to consume all gas and bubble-up the effects, since\n // neither revert or assert consume all gas since Solidity 0.8.0\n // https://docs.soliditylang.org/en/v0.8.0/control-structures.html#panic-via-assert-and-error-via-require\n /// @solidity memory-safe-assembly\n assembly {\n invalid()\n }\n }\n\n return (success, returndata);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155Upgradeable is IERC165Upgradeable {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 IERC20Upgradeable {\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 /**\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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/draft-IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.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 SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n function safeTransfer(\n IERC20Upgradeable 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 IERC20Upgradeable 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 IERC20Upgradeable 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 IERC20Upgradeable 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 IERC20Upgradeable 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 function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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(IERC20Upgradeable 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" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721Upgradeable.sol\";\nimport \"./IERC721ReceiverUpgradeable.sol\";\nimport \"./extensions/IERC721MetadataUpgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../utils/StringsUpgradeable.sol\";\nimport \"../../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {\n using AddressUpgradeable for address;\n using StringsUpgradeable for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC721_init_unchained(name_, symbol_);\n }\n\n function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\n return\n interfaceId == type(IERC721Upgradeable).interfaceId ||\n interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _ownerOf(tokenId);\n require(owner != address(0), \"ERC721: invalid token ID\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not token owner or approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n _requireMinted(tokenId);\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n _safeTransfer(from, to, tokenId, data);\n }\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 * `data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\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 `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 _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n */\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n return _owners[tokenId];\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _ownerOf(tokenId) != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\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 _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n unchecked {\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\n // Given that tokens are minted one by one, it is impossible in practice that\n // this ever happens. Might change if we allow batch minting.\n // The ERC fails to describe this case.\n _balances[to] += 1;\n }\n\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId, 1);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n * This is an internal function that does not check if the sender is authorized to operate on the token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n owner = ERC721Upgradeable.ownerOf(tokenId);\n\n // Clear approvals\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // Cannot overflow, as that would require more tokens to be burned/transferred\n // out than the owner initially received through minting and transferring in.\n _balances[owner] -= 1;\n }\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId, 1);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId, 1);\n\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n // Clear approvals from the previous owner\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n // `from`'s balance is the number of token held, which is at least one before the current\n // transfer.\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n // all 2**256 token ids to be minted, which in practice is impossible.\n _balances[from] -= 1;\n _balances[to] += 1;\n }\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId, 1);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits an {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n * - When `from` is zero, the tokens will be minted for `to`.\n * - When `to` is zero, ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256, /* firstTokenId */\n uint256 batchSize\n ) internal virtual {\n if (batchSize > 1) {\n if (from != address(0)) {\n _balances[from] -= batchSize;\n }\n if (to != address(0)) {\n _balances[to] += batchSize;\n }\n }\n }\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n * - When `from` is zero, the tokens were minted for `to`.\n * - When `to` is zero, ``from``'s tokens were burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 firstTokenId,\n uint256 batchSize\n ) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721Upgradeable.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721ReceiverUpgradeable {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\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`.\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 /**\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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\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 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 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 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" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or 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 _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\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" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../StringsUpgradeable.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", StringsUpgradeable.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSAUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n *\n * @custom:storage-size 52\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProofUpgradeable {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(\n bytes32[] calldata proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value for the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n return hashes[totalHashes - 1];\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value for the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n return hashes[totalHashes - 1];\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable {\n function __ERC165_init() internal onlyInitializing {\n }\n\n function __ERC165_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165Upgradeable).interfaceId;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.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 IERC165Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\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 return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\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\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\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 /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = MathUpgradeable.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSetUpgradeable {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(account),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerable.sol\";\nimport \"./AccessControl.sol\";\nimport \"../utils/structs/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override {\n super._grantRole(role, account);\n _roleMembers[role].add(account);\n }\n\n /**\n * @dev Overload {_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override {\n super._revokeRole(role, account);\n _roleMembers[role].remove(account);\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControlEnumerable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\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" + }, + "@openzeppelin/contracts/governance/utils/IVotes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)\npragma solidity ^0.8.0;\n\n/**\n * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.\n *\n * _Available since v4.5._\n */\ninterface IVotes {\n /**\n * @dev Emitted when an account changes their delegate.\n */\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /**\n * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\n */\n event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);\n\n /**\n * @dev Returns the current amount of votes that `account` has.\n */\n function getVotes(address account) external view returns (uint256);\n\n /**\n * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).\n */\n function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).\n *\n * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.\n * Votes that have not been delegated are still part of total supply, even though they would not participate in a\n * vote.\n */\n function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);\n\n /**\n * @dev Returns the delegate that `account` has chosen.\n */\n function delegates(address account) external view returns (address);\n\n /**\n * @dev Delegates votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) external;\n\n /**\n * @dev Delegates votes from signer to `delegatee`.\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../../access/Ownable.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\n * implementation contract, which is where they will delegate all function calls.\n *\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\n */\ncontract UpgradeableBeacon is IBeacon, Ownable {\n address private _implementation;\n\n /**\n * @dev Emitted when the implementation returned by the beacon is changed.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\n * beacon.\n */\n constructor(address implementation_) {\n _setImplementation(implementation_);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function implementation() public view virtual override returns (address) {\n return _implementation;\n }\n\n /**\n * @dev Upgrades the beacon to a new implementation.\n *\n * Emits an {Upgraded} event.\n *\n * Requirements:\n *\n * - msg.sender must be the owner of the contract.\n * - `newImplementation` must be a contract.\n */\n function upgradeTo(address newImplementation) public virtual onlyOwner {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation contract address for this beacon\n *\n * Requirements:\n *\n * - `newImplementation` must be a contract.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\n _implementation = newImplementation;\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts/security/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./draft-IERC20Permit.sol\";\nimport \"../ERC20.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\nimport \"../../../utils/cryptography/EIP712.sol\";\nimport \"../../../utils/Counters.sol\";\n\n/**\n * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping(address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private constant _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n /**\n * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.\n * However, to ensure consistency with the upgradeable transpiler, we will continue\n * to reserve a slot.\n * @custom:oz-renamed-from _PERMIT_TYPEHASH\n */\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) EIP712(name, \"1\") {}\n\n /**\n * @dev See {IERC20Permit-permit}.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view virtual override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n\n /**\n * @dev \"Consume a nonce\": return the current value and increment.\n *\n * _Available since v4.1._\n */\n function _useNonce(address owner) internal virtual returns (uint256 current) {\n Counters.Counter storage nonce = _nonces[owner];\n current = nonce.current();\n nonce.increment();\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n */\nabstract contract ERC20Pausable is ERC20, Pausable {\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (token/ERC20/extensions/ERC20Votes.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./draft-ERC20Permit.sol\";\nimport \"../../../utils/math/Math.sol\";\nimport \"../../../governance/utils/IVotes.sol\";\nimport \"../../../utils/math/SafeCast.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\n\n/**\n * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's,\n * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1.\n *\n * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module.\n *\n * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either\n * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting\n * power can be queried through the public accessors {getVotes} and {getPastVotes}.\n *\n * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it\n * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked.\n *\n * _Available since v4.2._\n */\nabstract contract ERC20Votes is IVotes, ERC20Permit {\n struct Checkpoint {\n uint32 fromBlock;\n uint224 votes;\n }\n\n bytes32 private constant _DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n mapping(address => address) private _delegates;\n mapping(address => Checkpoint[]) private _checkpoints;\n Checkpoint[] private _totalSupplyCheckpoints;\n\n /**\n * @dev Get the `pos`-th checkpoint for `account`.\n */\n function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) {\n return _checkpoints[account][pos];\n }\n\n /**\n * @dev Get number of checkpoints for `account`.\n */\n function numCheckpoints(address account) public view virtual returns (uint32) {\n return SafeCast.toUint32(_checkpoints[account].length);\n }\n\n /**\n * @dev Get the address `account` is currently delegating to.\n */\n function delegates(address account) public view virtual override returns (address) {\n return _delegates[account];\n }\n\n /**\n * @dev Gets the current votes balance for `account`\n */\n function getVotes(address account) public view virtual override returns (uint256) {\n uint256 pos = _checkpoints[account].length;\n return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes;\n }\n\n /**\n * @dev Retrieve the number of votes for `account` at the end of `blockNumber`.\n *\n * Requirements:\n *\n * - `blockNumber` must have been already mined\n */\n function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) {\n require(blockNumber < block.number, \"ERC20Votes: block not yet mined\");\n return _checkpointsLookup(_checkpoints[account], blockNumber);\n }\n\n /**\n * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances.\n * It is but NOT the sum of all the delegated votes!\n *\n * Requirements:\n *\n * - `blockNumber` must have been already mined\n */\n function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) {\n require(blockNumber < block.number, \"ERC20Votes: block not yet mined\");\n return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber);\n }\n\n /**\n * @dev Lookup a value in a list of (sorted) checkpoints.\n */\n function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) {\n // We run a binary search to look for the earliest checkpoint taken after `blockNumber`.\n //\n // Initially we check if the block is recent to narrow the search range.\n // During the loop, the index of the wanted checkpoint remains in the range [low-1, high).\n // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant.\n // - If the middle checkpoint is after `blockNumber`, we look in [low, mid)\n // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high)\n // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not\n // out of bounds (in which case we're looking too far in the past and the result is 0).\n // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is\n // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out\n // the same.\n uint256 length = ckpts.length;\n\n uint256 low = 0;\n uint256 high = length;\n\n if (length > 5) {\n uint256 mid = length - Math.sqrt(length);\n if (_unsafeAccess(ckpts, mid).fromBlock > blockNumber) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n while (low < high) {\n uint256 mid = Math.average(low, high);\n if (_unsafeAccess(ckpts, mid).fromBlock > blockNumber) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes;\n }\n\n /**\n * @dev Delegate votes from the sender to `delegatee`.\n */\n function delegate(address delegatee) public virtual override {\n _delegate(_msgSender(), delegatee);\n }\n\n /**\n * @dev Delegates votes from signer to `delegatee`\n */\n function delegateBySig(\n address delegatee,\n uint256 nonce,\n uint256 expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n require(block.timestamp <= expiry, \"ERC20Votes: signature expired\");\n address signer = ECDSA.recover(\n _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))),\n v,\n r,\n s\n );\n require(nonce == _useNonce(signer), \"ERC20Votes: invalid nonce\");\n _delegate(signer, delegatee);\n }\n\n /**\n * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1).\n */\n function _maxSupply() internal view virtual returns (uint224) {\n return type(uint224).max;\n }\n\n /**\n * @dev Snapshots the totalSupply after it has been increased.\n */\n function _mint(address account, uint256 amount) internal virtual override {\n super._mint(account, amount);\n require(totalSupply() <= _maxSupply(), \"ERC20Votes: total supply risks overflowing votes\");\n\n _writeCheckpoint(_totalSupplyCheckpoints, _add, amount);\n }\n\n /**\n * @dev Snapshots the totalSupply after it has been decreased.\n */\n function _burn(address account, uint256 amount) internal virtual override {\n super._burn(account, amount);\n\n _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount);\n }\n\n /**\n * @dev Move voting power when tokens are transferred.\n *\n * Emits a {IVotes-DelegateVotesChanged} event.\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._afterTokenTransfer(from, to, amount);\n\n _moveVotingPower(delegates(from), delegates(to), amount);\n }\n\n /**\n * @dev Change delegation for `delegator` to `delegatee`.\n *\n * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}.\n */\n function _delegate(address delegator, address delegatee) internal virtual {\n address currentDelegate = delegates(delegator);\n uint256 delegatorBalance = balanceOf(delegator);\n _delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n _moveVotingPower(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _moveVotingPower(\n address src,\n address dst,\n uint256 amount\n ) private {\n if (src != dst && amount > 0) {\n if (src != address(0)) {\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount);\n emit DelegateVotesChanged(src, oldWeight, newWeight);\n }\n\n if (dst != address(0)) {\n (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount);\n emit DelegateVotesChanged(dst, oldWeight, newWeight);\n }\n }\n }\n\n function _writeCheckpoint(\n Checkpoint[] storage ckpts,\n function(uint256, uint256) view returns (uint256) op,\n uint256 delta\n ) private returns (uint256 oldWeight, uint256 newWeight) {\n uint256 pos = ckpts.length;\n\n Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1);\n\n oldWeight = oldCkpt.votes;\n newWeight = op(oldWeight, delta);\n\n if (pos > 0 && oldCkpt.fromBlock == block.number) {\n _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight);\n } else {\n ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)}));\n }\n }\n\n function _add(uint256 a, uint256 b) private pure returns (uint256) {\n return a + b;\n }\n\n function _subtract(uint256 a, uint256 b) private pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.\n */\n function _unsafeAccess(Checkpoint[] storage ckpts, uint256 pos) private pure returns (Checkpoint storage result) {\n assembly {\n mstore(0, ckpts.slot)\n result.slot := add(keccak256(0, 0x20), pos)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 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 /**\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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../extensions/ERC20Burnable.sol\";\nimport \"../extensions/ERC20Pausable.sol\";\nimport \"../../../access/AccessControlEnumerable.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev {ERC20} token, including:\n *\n * - ability for holders to burn (destroy) their tokens\n * - a minter role that allows for token minting (creation)\n * - a pauser role that allows to stop all token transfers\n *\n * This contract uses {AccessControl} to lock permissioned functions using the\n * different roles - head to its documentation for details.\n *\n * The account that deploys the contract will be granted the minter and pauser\n * roles, as well as the default admin role, which will let it grant both minter\n * and pauser roles to other accounts.\n *\n * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._\n */\ncontract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /**\n * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the\n * account that deploys the contract.\n *\n * See {ERC20-constructor}.\n */\n constructor(string memory name, string memory symbol) ERC20(name, symbol) {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`.\n *\n * See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(address to, uint256 amount) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have minter role to mint\");\n _mint(to, amount);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to pause\");\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to unpause\");\n _unpause();\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20, ERC20Pausable) {\n super._beforeTokenTransfer(from, to, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or 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 _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\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" + }, + "@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" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "@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" + }, + "@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" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\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 return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\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\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\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 /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "contracts/CollateralManager.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n// Libraries\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\n// Interfaces\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\";\nimport \"./interfaces/ICollateralManager.sol\";\nimport { Collateral, CollateralType, ICollateralEscrowV1 } from \"./interfaces/escrow/ICollateralEscrowV1.sol\";\nimport \"./interfaces/ITellerV2.sol\";\nimport \"./interfaces/IProtocolPausingManager.sol\";\nimport \"./interfaces/IHasProtocolPausingManager.sol\";\ncontract CollateralManager is OwnableUpgradeable, ICollateralManager {\n /* Storage */\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n ITellerV2 public tellerV2;\n address private collateralEscrowBeacon; // The address of the escrow contract beacon\n\n // bidIds -> collateralEscrow\n mapping(uint256 => address) public _escrows;\n // bidIds -> validated collateral info\n mapping(uint256 => CollateralInfo) internal _bidCollaterals;\n\n /**\n * Since collateralInfo is mapped (address assetAddress => Collateral) that means\n * that only a single tokenId per nft per loan can be collateralized.\n * Ex. Two bored apes cannot be used as collateral for a single loan.\n */\n struct CollateralInfo {\n EnumerableSetUpgradeable.AddressSet collateralAddresses;\n mapping(address => Collateral) collateralInfo;\n }\n\n /* Events */\n event CollateralEscrowDeployed(uint256 _bidId, address _collateralEscrow);\n event CollateralCommitted(\n uint256 _bidId,\n CollateralType _type,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId\n );\n event CollateralClaimed(uint256 _bidId);\n event CollateralDeposited(\n uint256 _bidId,\n CollateralType _type,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId\n );\n event CollateralWithdrawn(\n uint256 _bidId,\n CollateralType _type,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId,\n address _recipient\n );\n\n /* Modifiers */\n modifier onlyTellerV2() {\n require(_msgSender() == address(tellerV2), \"Sender not authorized\");\n _;\n }\n\n modifier onlyProtocolOwner() {\n\n address protocolOwner = OwnableUpgradeable(address(tellerV2)).owner();\n\n require(_msgSender() == protocolOwner, \"Sender not authorized\");\n _;\n }\n\n modifier whenProtocolNotPaused() { \n address pausingManager = IHasProtocolPausingManager( address(tellerV2) ).getProtocolPausingManager();\n\n require( IProtocolPausingManager(address(pausingManager)).protocolPaused() == false , \"Protocol is paused\");\n _;\n }\n\n /* External Functions */\n\n /**\n * @notice Initializes the collateral manager.\n * @param _collateralEscrowBeacon The address of the escrow implementation.\n * @param _tellerV2 The address of the protocol.\n */\n function initialize(address _collateralEscrowBeacon, address _tellerV2)\n external\n initializer\n {\n collateralEscrowBeacon = _collateralEscrowBeacon;\n tellerV2 = ITellerV2(_tellerV2);\n __Ownable_init_unchained();\n }\n\n /**\n * @notice Sets the address of the Beacon contract used for the collateral escrow contracts.\n * @param _collateralEscrowBeacon The address of the Beacon contract.\n */\n function setCollateralEscrowBeacon(address _collateralEscrowBeacon)\n external\n reinitializer(2)\n {\n collateralEscrowBeacon = _collateralEscrowBeacon;\n }\n\n /**\n * @notice Checks to see if a bid is backed by collateral.\n * @param _bidId The id of the bid to check.\n */\n\n function isBidCollateralBacked(uint256 _bidId)\n public\n virtual\n returns (bool)\n {\n return _bidCollaterals[_bidId].collateralAddresses.length() > 0;\n }\n\n /**\n * @notice Checks the validity of a borrower's multiple collateral balances and commits it to a bid.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral assets.\n * @return validation_ Boolean indicating if the collateral balances were validated.\n */\n function commitCollateral(\n uint256 _bidId,\n Collateral[] calldata _collateralInfo\n ) public onlyTellerV2 returns (bool validation_) {\n address borrower = tellerV2.getLoanBorrower(_bidId);\n require(borrower != address(0), \"Loan has no borrower\");\n (validation_, ) = checkBalances(borrower, _collateralInfo);\n\n //if the collateral info is valid, call commitCollateral for each one\n if (validation_) {\n for (uint256 i; i < _collateralInfo.length; i++) {\n Collateral memory info = _collateralInfo[i];\n _commitCollateral(_bidId, info);\n }\n }\n }\n\n /**\n * @notice Checks the validity of a borrower's collateral balance and commits it to a bid.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral asset.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function commitCollateral(\n uint256 _bidId,\n Collateral calldata _collateralInfo\n ) public onlyTellerV2 returns (bool validation_) {\n address borrower = tellerV2.getLoanBorrower(_bidId);\n require(borrower != address(0), \"Loan has no borrower\");\n validation_ = _checkBalance(borrower, _collateralInfo);\n if (validation_) {\n _commitCollateral(_bidId, _collateralInfo);\n }\n }\n\n /**\n * @notice Re-checks the validity of a borrower's collateral balance committed to a bid.\n * @param _bidId The id of the associated bid.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function revalidateCollateral(uint256 _bidId)\n external\n returns (bool validation_)\n {\n Collateral[] memory collateralInfos = getCollateralInfo(_bidId);\n address borrower = tellerV2.getLoanBorrower(_bidId);\n (validation_, ) = _checkBalances(borrower, collateralInfos, true);\n }\n\n /**\n * @notice Checks the validity of a borrower's multiple collateral balances.\n * @param _borrowerAddress The address of the borrower holding the collateral.\n * @param _collateralInfo Additional information about the collateral assets.\n */\n function checkBalances(\n address _borrowerAddress,\n Collateral[] calldata _collateralInfo\n ) public returns (bool validated_, bool[] memory checks_) {\n return _checkBalances(_borrowerAddress, _collateralInfo, false);\n }\n\n /**\n * @notice Deploys a new collateral escrow and deposits collateral.\n * @param _bidId The associated bidId of the collateral escrow.\n */\n function deployAndDeposit(uint256 _bidId) external onlyTellerV2 {\n if (isBidCollateralBacked(_bidId)) {\n //attempt deploy a new collateral escrow contract if there is not already one. Otherwise fetch it.\n (address proxyAddress, ) = _deployEscrow(_bidId);\n _escrows[_bidId] = proxyAddress;\n\n //for each bid collateral associated with this loan, deposit the collateral into escrow\n for (\n uint256 i;\n i < _bidCollaterals[_bidId].collateralAddresses.length();\n i++\n ) {\n _deposit(\n _bidId,\n _bidCollaterals[_bidId].collateralInfo[\n _bidCollaterals[_bidId].collateralAddresses.at(i)\n ]\n );\n }\n\n emit CollateralEscrowDeployed(_bidId, proxyAddress);\n }\n }\n\n /**\n * @notice Gets the address of a deployed escrow.\n * @notice _bidId The bidId to return the escrow for.\n * @return The address of the escrow.\n */\n function getEscrow(uint256 _bidId) external view returns (address) {\n return _escrows[_bidId];\n }\n\n /**\n * @notice Gets the collateral info for a given bid id.\n * @param _bidId The bidId to return the collateral info for.\n * @return infos_ The stored collateral info.\n */\n function getCollateralInfo(uint256 _bidId)\n public\n view\n returns (Collateral[] memory infos_)\n {\n CollateralInfo storage collateral = _bidCollaterals[_bidId];\n address[] memory collateralAddresses = collateral\n .collateralAddresses\n .values();\n infos_ = new Collateral[](collateralAddresses.length);\n for (uint256 i; i < collateralAddresses.length; i++) {\n infos_[i] = collateral.collateralInfo[collateralAddresses[i]];\n }\n }\n\n /**\n * @notice Gets the collateral asset amount for a given bid id on the TellerV2 contract.\n * @param _bidId The ID of a bid on TellerV2.\n * @param _collateralAddress An address used as collateral.\n * @return amount_ The amount of collateral of type _collateralAddress.\n */\n function getCollateralAmount(uint256 _bidId, address _collateralAddress)\n public\n view\n returns (uint256 amount_)\n {\n amount_ = _bidCollaterals[_bidId]\n .collateralInfo[_collateralAddress]\n ._amount;\n }\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid that has been successfully repaid.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function withdraw(uint256 _bidId) external whenProtocolNotPaused {\n BidState bidState = tellerV2.getBidState(_bidId);\n\n require(bidState == BidState.PAID, \"collateral cannot be withdrawn\");\n\n _withdraw(_bidId, tellerV2.getLoanBorrower(_bidId));\n\n emit CollateralClaimed(_bidId);\n }\n\n function withdrawDustTokens(\n uint256 _bidId, \n address _tokenAddress, \n uint256 _amount,\n address _recipientAddress\n ) external onlyProtocolOwner whenProtocolNotPaused {\n\n ICollateralEscrowV1(_escrows[_bidId]).withdrawDustTokens(\n _tokenAddress,\n _amount,\n _recipientAddress\n );\n }\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid that has been CLOSED after being defaulted.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function lenderClaimCollateral(uint256 _bidId) external onlyTellerV2 whenProtocolNotPaused {\n if (isBidCollateralBacked(_bidId)) {\n BidState bidState = tellerV2.getBidState(_bidId);\n\n require(\n bidState == BidState.CLOSED,\n \"Loan has not been liquidated\"\n );\n\n _withdraw(_bidId, tellerV2.getLoanLender(_bidId));\n emit CollateralClaimed(_bidId);\n }\n }\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid that has been CLOSED after being defaulted.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function lenderClaimCollateralWithRecipient(uint256 _bidId, address _collateralRecipient) external onlyTellerV2 whenProtocolNotPaused {\n if (isBidCollateralBacked(_bidId)) {\n BidState bidState = tellerV2.getBidState(_bidId);\n\n require(\n bidState == BidState.CLOSED,\n \"Loan has not been liquidated\"\n );\n\n _withdraw(_bidId, _collateralRecipient);\n emit CollateralClaimed(_bidId);\n }\n }\n\n /**\n * @notice Sends the deposited collateral to a liquidator of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n * @param _liquidatorAddress The address of the liquidator to send the collateral to.\n */\n function liquidateCollateral(uint256 _bidId, address _liquidatorAddress)\n external\n onlyTellerV2\n whenProtocolNotPaused\n {\n if (isBidCollateralBacked(_bidId)) {\n BidState bidState = tellerV2.getBidState(_bidId);\n require(\n bidState == BidState.LIQUIDATED,\n \"Loan has not been liquidated\"\n );\n _withdraw(_bidId, _liquidatorAddress);\n }\n }\n\n /* Internal Functions */\n\n /**\n * @notice Deploys a new collateral escrow.\n * @param _bidId The associated bidId of the collateral escrow.\n */\n function _deployEscrow(uint256 _bidId)\n internal\n virtual\n returns (address proxyAddress_, address borrower_)\n {\n proxyAddress_ = _escrows[_bidId];\n // Get bid info\n borrower_ = tellerV2.getLoanBorrower(_bidId);\n if (proxyAddress_ == address(0)) {\n require(borrower_ != address(0), \"Bid does not exist\");\n\n BeaconProxy proxy = new BeaconProxy(\n collateralEscrowBeacon,\n abi.encodeWithSelector(\n ICollateralEscrowV1.initialize.selector,\n _bidId\n )\n );\n proxyAddress_ = address(proxy);\n }\n }\n\n /*\n * @notice Deploys a new collateral escrow contract. Deposits collateral into a collateral escrow.\n * @param _bidId The associated bidId of the collateral escrow.\n * @param collateralInfo The collateral info to deposit.\n\n */\n function _deposit(uint256 _bidId, Collateral memory collateralInfo)\n internal\n virtual\n {\n require(collateralInfo._amount > 0, \"Collateral not validated\");\n (address escrowAddress, address borrower) = _deployEscrow(_bidId);\n ICollateralEscrowV1 collateralEscrow = ICollateralEscrowV1(\n escrowAddress\n );\n // Pull collateral from borrower & deposit into escrow\n if (collateralInfo._collateralType == CollateralType.ERC20) {\n IERC20Upgradeable(collateralInfo._collateralAddress).transferFrom(\n borrower,\n address(this),\n collateralInfo._amount\n );\n IERC20Upgradeable(collateralInfo._collateralAddress).approve(\n escrowAddress,\n collateralInfo._amount\n );\n collateralEscrow.depositAsset(\n CollateralType.ERC20,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n 0\n );\n } else if (collateralInfo._collateralType == CollateralType.ERC721) {\n IERC721Upgradeable(collateralInfo._collateralAddress).transferFrom(\n borrower,\n address(this),\n collateralInfo._tokenId\n );\n IERC721Upgradeable(collateralInfo._collateralAddress).approve(\n escrowAddress,\n collateralInfo._tokenId\n );\n collateralEscrow.depositAsset(\n CollateralType.ERC721,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n collateralInfo._tokenId\n );\n } else if (collateralInfo._collateralType == CollateralType.ERC1155) {\n bytes memory data;\n IERC1155Upgradeable(collateralInfo._collateralAddress)\n .safeTransferFrom(\n borrower,\n address(this),\n collateralInfo._tokenId,\n collateralInfo._amount,\n data\n );\n IERC1155Upgradeable(collateralInfo._collateralAddress)\n .setApprovalForAll(escrowAddress, true);\n collateralEscrow.depositAsset(\n CollateralType.ERC1155,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n collateralInfo._tokenId\n );\n } else {\n revert(\"Unexpected collateral type\");\n }\n emit CollateralDeposited(\n _bidId,\n collateralInfo._collateralType,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n collateralInfo._tokenId\n );\n }\n\n /**\n * @notice Withdraws collateral to a given receiver's address.\n * @param _bidId The id of the bid to withdraw collateral for.\n * @param _receiver The address to withdraw the collateral to.\n */\n function _withdraw(uint256 _bidId, address _receiver) internal virtual {\n for (\n uint256 i;\n i < _bidCollaterals[_bidId].collateralAddresses.length();\n i++\n ) {\n // Get collateral info\n Collateral storage collateralInfo = _bidCollaterals[_bidId]\n .collateralInfo[\n _bidCollaterals[_bidId].collateralAddresses.at(i)\n ];\n // Withdraw collateral from escrow and send it to bid lender\n ICollateralEscrowV1(_escrows[_bidId]).withdraw(\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n _receiver\n );\n emit CollateralWithdrawn(\n _bidId,\n collateralInfo._collateralType,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n collateralInfo._tokenId,\n _receiver\n );\n }\n }\n\n /**\n * @notice Checks the validity of a borrower's collateral balance and commits it to a bid.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral asset.\n */\n function _commitCollateral(\n uint256 _bidId,\n Collateral memory _collateralInfo\n ) internal virtual {\n CollateralInfo storage collateral = _bidCollaterals[_bidId];\n\n require(\n !collateral.collateralAddresses.contains(\n _collateralInfo._collateralAddress\n ),\n \"Cannot commit multiple collateral with the same address\"\n );\n require(\n _collateralInfo._collateralType != CollateralType.ERC721 ||\n _collateralInfo._amount == 1,\n \"ERC721 collateral must have amount of 1\"\n );\n\n collateral.collateralAddresses.add(_collateralInfo._collateralAddress);\n collateral.collateralInfo[\n _collateralInfo._collateralAddress\n ] = _collateralInfo;\n emit CollateralCommitted(\n _bidId,\n _collateralInfo._collateralType,\n _collateralInfo._collateralAddress,\n _collateralInfo._amount,\n _collateralInfo._tokenId\n );\n }\n\n /**\n * @notice Checks the validity of a borrower's multiple collateral balances.\n * @param _borrowerAddress The address of the borrower holding the collateral.\n * @param _collateralInfo Additional information about the collateral assets.\n * @param _shortCircut if true, will return immediately until an invalid balance\n */\n function _checkBalances(\n address _borrowerAddress,\n Collateral[] memory _collateralInfo,\n bool _shortCircut\n ) internal virtual returns (bool validated_, bool[] memory checks_) {\n checks_ = new bool[](_collateralInfo.length);\n validated_ = true;\n for (uint256 i; i < _collateralInfo.length; i++) {\n bool isValidated = _checkBalance(\n _borrowerAddress,\n _collateralInfo[i]\n );\n checks_[i] = isValidated;\n if (!isValidated) {\n validated_ = false;\n //if short circuit is true, return on the first invalid balance to save execution cycles. Values of checks[] will be invalid/undetermined if shortcircuit is true.\n if (_shortCircut) {\n return (validated_, checks_);\n }\n }\n }\n }\n\n /**\n * @notice Checks the validity of a borrower's single collateral balance.\n * @param _borrowerAddress The address of the borrower holding the collateral.\n * @param _collateralInfo Additional information about the collateral asset.\n * @return validation_ Boolean indicating if the collateral balances were validated.\n */\n function _checkBalance(\n address _borrowerAddress,\n Collateral memory _collateralInfo\n ) internal virtual returns (bool) {\n CollateralType collateralType = _collateralInfo._collateralType;\n\n if (collateralType == CollateralType.ERC20) {\n return\n _collateralInfo._amount <=\n IERC20Upgradeable(_collateralInfo._collateralAddress).balanceOf(\n _borrowerAddress\n );\n } else if (collateralType == CollateralType.ERC721) {\n return\n _borrowerAddress ==\n IERC721Upgradeable(_collateralInfo._collateralAddress).ownerOf(\n _collateralInfo._tokenId\n );\n } else if (collateralType == CollateralType.ERC1155) {\n return\n _collateralInfo._amount <=\n IERC1155Upgradeable(_collateralInfo._collateralAddress)\n .balanceOf(_borrowerAddress, _collateralInfo._tokenId);\n } else {\n return false;\n }\n }\n\n // On NFT Received handlers\n\n function onERC721Received(address, address, uint256, bytes calldata)\n external\n pure\n returns (bytes4)\n {\n return\n bytes4(\n keccak256(\"onERC721Received(address,address,uint256,bytes)\")\n );\n }\n\n function onERC1155Received(\n address,\n address,\n uint256 id,\n uint256 value,\n bytes calldata\n ) external returns (bytes4) {\n return\n bytes4(\n keccak256(\n \"onERC1155Received(address,address,uint256,uint256,bytes)\"\n )\n );\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] calldata _ids,\n uint256[] calldata _values,\n bytes calldata\n ) external returns (bytes4) {\n require(\n _ids.length == 1,\n \"Only allowed one asset batch transfer per transaction.\"\n );\n return\n bytes4(\n keccak256(\n \"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"\n )\n );\n }\n}\n" + }, + "contracts/EAS/TellerAS.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"../Types.sol\";\nimport \"../interfaces/IEAS.sol\";\nimport \"../interfaces/IASRegistry.sol\";\n\n/**\n * @title TellerAS - Teller Attestation Service - based on EAS - Ethereum Attestation Service\n */\ncontract TellerAS is IEAS {\n error AccessDenied();\n error AlreadyRevoked();\n error InvalidAttestation();\n error InvalidExpirationTime();\n error InvalidOffset();\n error InvalidRegistry();\n error InvalidSchema();\n error InvalidVerifier();\n error NotFound();\n error NotPayable();\n\n string public constant VERSION = \"0.8\";\n\n // A terminator used when concatenating and hashing multiple fields.\n string private constant HASH_TERMINATOR = \"@\";\n\n // The AS global registry.\n IASRegistry private immutable _asRegistry;\n\n // The EIP712 verifier used to verify signed attestations.\n IEASEIP712Verifier private immutable _eip712Verifier;\n\n // A mapping between attestations and their related attestations.\n mapping(bytes32 => bytes32[]) private _relatedAttestations;\n\n // A mapping between an account and its received attestations.\n mapping(address => mapping(bytes32 => bytes32[]))\n private _receivedAttestations;\n\n // A mapping between an account and its sent attestations.\n mapping(address => mapping(bytes32 => bytes32[])) private _sentAttestations;\n\n // A mapping between a schema and its attestations.\n mapping(bytes32 => bytes32[]) private _schemaAttestations;\n\n // The global mapping between attestations and their UUIDs.\n mapping(bytes32 => Attestation) private _db;\n\n // The global counter for the total number of attestations.\n uint256 private _attestationsCount;\n\n bytes32 private _lastUUID;\n\n /**\n * @dev Creates a new EAS instance.\n *\n * @param registry The address of the global AS registry.\n * @param verifier The address of the EIP712 verifier.\n */\n constructor(IASRegistry registry, IEASEIP712Verifier verifier) {\n if (address(registry) == address(0x0)) {\n revert InvalidRegistry();\n }\n\n if (address(verifier) == address(0x0)) {\n revert InvalidVerifier();\n }\n\n _asRegistry = registry;\n _eip712Verifier = verifier;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getASRegistry() external view override returns (IASRegistry) {\n return _asRegistry;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getEIP712Verifier()\n external\n view\n override\n returns (IEASEIP712Verifier)\n {\n return _eip712Verifier;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getAttestationsCount() external view override returns (uint256) {\n return _attestationsCount;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data\n ) public payable virtual override returns (bytes32) {\n return\n _attest(\n recipient,\n schema,\n expirationTime,\n refUUID,\n data,\n msg.sender\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function attestByDelegation(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public payable virtual override returns (bytes32) {\n _eip712Verifier.attest(\n recipient,\n schema,\n expirationTime,\n refUUID,\n data,\n attester,\n v,\n r,\n s\n );\n\n return\n _attest(recipient, schema, expirationTime, refUUID, data, attester);\n }\n\n /**\n * @inheritdoc IEAS\n */\n function revoke(bytes32 uuid) public virtual override {\n return _revoke(uuid, msg.sender);\n }\n\n /**\n * @inheritdoc IEAS\n */\n function revokeByDelegation(\n bytes32 uuid,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n _eip712Verifier.revoke(uuid, attester, v, r, s);\n\n _revoke(uuid, attester);\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getAttestation(bytes32 uuid)\n external\n view\n override\n returns (Attestation memory)\n {\n return _db[uuid];\n }\n\n /**\n * @inheritdoc IEAS\n */\n function isAttestationValid(bytes32 uuid)\n public\n view\n override\n returns (bool)\n {\n return _db[uuid].uuid != 0;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function isAttestationActive(bytes32 uuid)\n public\n view\n virtual\n override\n returns (bool)\n {\n return\n isAttestationValid(uuid) &&\n _db[uuid].expirationTime >= block.timestamp &&\n _db[uuid].revocationTime == 0;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getReceivedAttestationUUIDs(\n address recipient,\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view override returns (bytes32[] memory) {\n return\n _sliceUUIDs(\n _receivedAttestations[recipient][schema],\n start,\n length,\n reverseOrder\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getReceivedAttestationUUIDsCount(address recipient, bytes32 schema)\n external\n view\n override\n returns (uint256)\n {\n return _receivedAttestations[recipient][schema].length;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getSentAttestationUUIDs(\n address attester,\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view override returns (bytes32[] memory) {\n return\n _sliceUUIDs(\n _sentAttestations[attester][schema],\n start,\n length,\n reverseOrder\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getSentAttestationUUIDsCount(address recipient, bytes32 schema)\n external\n view\n override\n returns (uint256)\n {\n return _sentAttestations[recipient][schema].length;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getRelatedAttestationUUIDs(\n bytes32 uuid,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view override returns (bytes32[] memory) {\n return\n _sliceUUIDs(\n _relatedAttestations[uuid],\n start,\n length,\n reverseOrder\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getRelatedAttestationUUIDsCount(bytes32 uuid)\n external\n view\n override\n returns (uint256)\n {\n return _relatedAttestations[uuid].length;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getSchemaAttestationUUIDs(\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view override returns (bytes32[] memory) {\n return\n _sliceUUIDs(\n _schemaAttestations[schema],\n start,\n length,\n reverseOrder\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getSchemaAttestationUUIDsCount(bytes32 schema)\n external\n view\n override\n returns (uint256)\n {\n return _schemaAttestations[schema].length;\n }\n\n /**\n * @dev Attests to a specific AS.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param expirationTime The expiration time of the attestation.\n * @param refUUID An optional related attestation's UUID.\n * @param data Additional custom data.\n * @param attester The attesting account.\n *\n * @return The UUID of the new attestation.\n */\n function _attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester\n ) private returns (bytes32) {\n if (expirationTime <= block.timestamp) {\n revert InvalidExpirationTime();\n }\n\n IASRegistry.ASRecord memory asRecord = _asRegistry.getAS(schema);\n if (asRecord.uuid == EMPTY_UUID) {\n revert InvalidSchema();\n }\n\n IASResolver resolver = asRecord.resolver;\n if (address(resolver) != address(0x0)) {\n if (msg.value != 0 && !resolver.isPayable()) {\n revert NotPayable();\n }\n\n if (\n !resolver.resolve{ value: msg.value }(\n recipient,\n asRecord.schema,\n data,\n expirationTime,\n attester\n )\n ) {\n revert InvalidAttestation();\n }\n }\n\n Attestation memory attestation = Attestation({\n uuid: EMPTY_UUID,\n schema: schema,\n recipient: recipient,\n attester: attester,\n time: block.timestamp,\n expirationTime: expirationTime,\n revocationTime: 0,\n refUUID: refUUID,\n data: data\n });\n\n _lastUUID = _getUUID(attestation);\n attestation.uuid = _lastUUID;\n\n _receivedAttestations[recipient][schema].push(_lastUUID);\n _sentAttestations[attester][schema].push(_lastUUID);\n _schemaAttestations[schema].push(_lastUUID);\n\n _db[_lastUUID] = attestation;\n _attestationsCount++;\n\n if (refUUID != 0) {\n if (!isAttestationValid(refUUID)) {\n revert NotFound();\n }\n\n _relatedAttestations[refUUID].push(_lastUUID);\n }\n\n emit Attested(recipient, attester, _lastUUID, schema);\n\n return _lastUUID;\n }\n\n function getLastUUID() external view returns (bytes32) {\n return _lastUUID;\n }\n\n /**\n * @dev Revokes an existing attestation to a specific AS.\n *\n * @param uuid The UUID of the attestation to revoke.\n * @param attester The attesting account.\n */\n function _revoke(bytes32 uuid, address attester) private {\n Attestation storage attestation = _db[uuid];\n if (attestation.uuid == EMPTY_UUID) {\n revert NotFound();\n }\n\n if (attestation.attester != attester) {\n revert AccessDenied();\n }\n\n if (attestation.revocationTime != 0) {\n revert AlreadyRevoked();\n }\n\n attestation.revocationTime = block.timestamp;\n\n emit Revoked(attestation.recipient, attester, uuid, attestation.schema);\n }\n\n /**\n * @dev Calculates a UUID for a given attestation.\n *\n * @param attestation The input attestation.\n *\n * @return Attestation UUID.\n */\n function _getUUID(Attestation memory attestation)\n private\n view\n returns (bytes32)\n {\n return\n keccak256(\n abi.encodePacked(\n attestation.schema,\n attestation.recipient,\n attestation.attester,\n attestation.time,\n attestation.expirationTime,\n attestation.data,\n HASH_TERMINATOR,\n _attestationsCount\n )\n );\n }\n\n /**\n * @dev Returns a slice in an array of attestation UUIDs.\n *\n * @param uuids The array of attestation UUIDs.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function _sliceUUIDs(\n bytes32[] memory uuids,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) private pure returns (bytes32[] memory) {\n uint256 attestationsLength = uuids.length;\n if (attestationsLength == 0) {\n return new bytes32[](0);\n }\n\n if (start >= attestationsLength) {\n revert InvalidOffset();\n }\n\n uint256 len = length;\n if (attestationsLength < start + length) {\n len = attestationsLength - start;\n }\n\n bytes32[] memory res = new bytes32[](len);\n\n for (uint256 i = 0; i < len; ++i) {\n res[i] = uuids[\n reverseOrder ? attestationsLength - (start + i + 1) : start + i\n ];\n }\n\n return res;\n }\n}\n" + }, + "contracts/EAS/TellerASEIP712Verifier.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"../interfaces/IEASEIP712Verifier.sol\";\n\n/**\n * @title EIP712 typed signatures verifier for EAS delegated attestations.\n */\ncontract TellerASEIP712Verifier is IEASEIP712Verifier {\n error InvalidSignature();\n\n string public constant VERSION = \"0.8\";\n\n // EIP712 domain separator, making signatures from different domains incompatible.\n bytes32 public immutable DOMAIN_SEPARATOR; // solhint-disable-line var-name-mixedcase\n\n // The hash of the data type used to relay calls to the attest function. It's the value of\n // keccak256(\"Attest(address recipient,bytes32 schema,uint256 expirationTime,bytes32 refUUID,bytes data,uint256 nonce)\").\n bytes32 public constant ATTEST_TYPEHASH =\n 0x39c0608dd995a3a25bfecb0fffe6801a81bae611d94438af988caa522d9d1476;\n\n // The hash of the data type used to relay calls to the revoke function. It's the value of\n // keccak256(\"Revoke(bytes32 uuid,uint256 nonce)\").\n bytes32 public constant REVOKE_TYPEHASH =\n 0xbae0931f3a99efd1b97c2f5b6b6e79d16418246b5055d64757e16de5ad11a8ab;\n\n // Replay protection nonces.\n mapping(address => uint256) private _nonces;\n\n /**\n * @dev Creates a new EIP712Verifier instance.\n */\n constructor() {\n uint256 chainId;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n chainId := chainid()\n }\n\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n ),\n keccak256(bytes(\"EAS\")),\n keccak256(bytes(VERSION)),\n chainId,\n address(this)\n )\n );\n }\n\n /**\n * @inheritdoc IEASEIP712Verifier\n */\n function getNonce(address account)\n external\n view\n override\n returns (uint256)\n {\n return _nonces[account];\n }\n\n /**\n * @inheritdoc IEASEIP712Verifier\n */\n function attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external override {\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(\n ATTEST_TYPEHASH,\n recipient,\n schema,\n expirationTime,\n refUUID,\n keccak256(data),\n _nonces[attester]++\n )\n )\n )\n );\n\n address recoveredAddress = ecrecover(digest, v, r, s);\n if (recoveredAddress == address(0) || recoveredAddress != attester) {\n revert InvalidSignature();\n }\n }\n\n /**\n * @inheritdoc IEASEIP712Verifier\n */\n function revoke(\n bytes32 uuid,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external override {\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(\n abi.encode(REVOKE_TYPEHASH, uuid, _nonces[attester]++)\n )\n )\n );\n\n address recoveredAddress = ecrecover(digest, v, r, s);\n if (recoveredAddress == address(0) || recoveredAddress != attester) {\n revert InvalidSignature();\n }\n }\n}\n" + }, + "contracts/EAS/TellerASRegistry.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"../Types.sol\";\nimport \"../interfaces/IASRegistry.sol\";\nimport \"../interfaces/IASResolver.sol\";\n\n/**\n * @title The global AS registry.\n */\ncontract TellerASRegistry is IASRegistry {\n error AlreadyExists();\n\n string public constant VERSION = \"0.8\";\n\n // The global mapping between AS records and their IDs.\n mapping(bytes32 => ASRecord) private _registry;\n\n // The global counter for the total number of attestations.\n uint256 private _asCount;\n\n /**\n * @inheritdoc IASRegistry\n */\n function register(bytes calldata schema, IASResolver resolver)\n external\n override\n returns (bytes32)\n {\n uint256 index = ++_asCount;\n\n ASRecord memory asRecord = ASRecord({\n uuid: EMPTY_UUID,\n index: index,\n schema: schema,\n resolver: resolver\n });\n\n bytes32 uuid = _getUUID(asRecord);\n if (_registry[uuid].uuid != EMPTY_UUID) {\n revert AlreadyExists();\n }\n\n asRecord.uuid = uuid;\n _registry[uuid] = asRecord;\n\n emit Registered(uuid, index, schema, resolver, msg.sender);\n\n return uuid;\n }\n\n /**\n * @inheritdoc IASRegistry\n */\n function getAS(bytes32 uuid)\n external\n view\n override\n returns (ASRecord memory)\n {\n return _registry[uuid];\n }\n\n /**\n * @inheritdoc IASRegistry\n */\n function getASCount() external view override returns (uint256) {\n return _asCount;\n }\n\n /**\n * @dev Calculates a UUID for a given AS.\n *\n * @param asRecord The input AS.\n *\n * @return AS UUID.\n */\n function _getUUID(ASRecord memory asRecord) private pure returns (bytes32) {\n return keccak256(abi.encodePacked(asRecord.schema, asRecord.resolver));\n }\n}\n" + }, + "contracts/EAS/TellerASResolver.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"../interfaces/IASResolver.sol\";\n\n/**\n * @title A base resolver contract\n */\nabstract contract TellerASResolver is IASResolver {\n error NotPayable();\n\n function isPayable() public pure virtual override returns (bool) {\n return false;\n }\n\n receive() external payable virtual {\n if (!isPayable()) {\n revert NotPayable();\n }\n }\n}\n" + }, + "contracts/ERC2771ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (metatx/ERC2771Context.sol)\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Context variant with ERC2771 support.\n * @dev This is modified from the OZ library to remove the gap of storage variables at the end.\n */\nabstract contract ERC2771ContextUpgradeable is\n Initializable,\n ContextUpgradeable\n{\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address private immutable _trustedForwarder;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address trustedForwarder) {\n _trustedForwarder = trustedForwarder;\n }\n\n function isTrustedForwarder(address forwarder)\n public\n view\n virtual\n returns (bool)\n {\n return forwarder == _trustedForwarder;\n }\n\n function _msgSender()\n internal\n view\n virtual\n override\n returns (address sender)\n {\n if (isTrustedForwarder(msg.sender)) {\n // The assembly code is more direct than the Solidity version using `abi.decode`.\n assembly {\n sender := shr(96, calldataload(sub(calldatasize(), 20)))\n }\n } else {\n return super._msgSender();\n }\n }\n\n function _msgData()\n internal\n view\n virtual\n override\n returns (bytes calldata)\n {\n if (isTrustedForwarder(msg.sender)) {\n return msg.data[:msg.data.length - 20];\n } else {\n return super._msgData();\n }\n }\n}\n" + }, + "contracts/escrow/CollateralEscrowV1.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n// Interfaces\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\";\nimport \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\ncontract CollateralEscrowV1 is OwnableUpgradeable, ICollateralEscrowV1 {\n uint256 public bidId;\n /* Mappings */\n mapping(address => Collateral) public collateralBalances; // collateral address -> collateral\n\n /* Events */\n event CollateralDeposited(address _collateralAddress, uint256 _amount);\n event CollateralWithdrawn(\n address _collateralAddress,\n uint256 _amount,\n address _recipient\n );\n\n /**\n * @notice Initializes an escrow.\n * @notice The id of the associated bid.\n */\n function initialize(uint256 _bidId) public initializer {\n __Ownable_init();\n bidId = _bidId;\n }\n\n /**\n * @notice Returns the id of the associated bid.\n * @return The id of the associated bid.\n */\n function getBid() external view returns (uint256) {\n return bidId;\n }\n\n /**\n * @notice Deposits a collateral asset into the escrow.\n * @param _collateralType The type of collateral asset to deposit (ERC721, ERC1155).\n * @param _collateralAddress The address of the collateral token.\n * @param _amount The amount to deposit.\n */\n function depositAsset(\n CollateralType _collateralType,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId\n ) external payable virtual onlyOwner {\n require(_amount > 0, \"Deposit amount cannot be zero\");\n _depositCollateral(\n _collateralType,\n _collateralAddress,\n _amount,\n _tokenId\n );\n Collateral storage collateral = collateralBalances[_collateralAddress];\n\n //Avoids asset overwriting. Can get rid of this restriction by restructuring collateral balances storage so it isnt a mapping based on address.\n require(\n collateral._amount == 0,\n \"Unable to deposit multiple collateral asset instances of the same contract address.\"\n );\n\n collateral._collateralType = _collateralType;\n collateral._amount = _amount;\n collateral._tokenId = _tokenId;\n emit CollateralDeposited(_collateralAddress, _amount);\n }\n\n /**\n * @notice Withdraws a collateral asset from the escrow.\n * @param _collateralAddress The address of the collateral contract.\n * @param _amount The amount to withdraw.\n * @param _recipient The address to send the assets to.\n */\n function withdraw(\n address _collateralAddress,\n uint256 _amount,\n address _recipient\n ) external virtual onlyOwner {\n require(_amount > 0, \"Withdraw amount cannot be zero\");\n Collateral storage collateral = collateralBalances[_collateralAddress];\n require(\n collateral._amount >= _amount,\n \"No collateral balance for asset\"\n );\n _withdrawCollateral(\n collateral,\n _collateralAddress,\n _amount,\n _recipient\n );\n collateral._amount -= _amount;\n emit CollateralWithdrawn(_collateralAddress, _amount, _recipient);\n }\n\n function withdrawDustTokens( \n address tokenAddress, \n uint256 amount,\n address recipient\n ) external virtual onlyOwner { //the owner should be collateral manager \n \n require(tokenAddress != address(0), \"Invalid token address\");\n\n Collateral storage collateral = collateralBalances[tokenAddress];\n require(\n collateral._amount == 0,\n \"Asset not allowed to be withdrawn as dust\"\n ); \n \n IERC20Upgradeable(tokenAddress).transfer(recipient, amount); \n }\n\n\n /**\n * @notice Internal function for transferring collateral assets into this contract.\n * @param _collateralAddress The address of the collateral contract.\n * @param _amount The amount to deposit.\n * @param _tokenId The token id of the collateral asset.\n */\n function _depositCollateral(\n CollateralType _collateralType,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId\n ) internal {\n // Deposit ERC20\n if (_collateralType == CollateralType.ERC20) {\n SafeERC20Upgradeable.safeTransferFrom(\n IERC20Upgradeable(_collateralAddress),\n _msgSender(),\n address(this),\n _amount\n );\n }\n // Deposit ERC721\n else if (_collateralType == CollateralType.ERC721) {\n require(_amount == 1, \"Incorrect deposit amount\");\n IERC721Upgradeable(_collateralAddress).transferFrom(\n _msgSender(),\n address(this),\n _tokenId\n );\n }\n // Deposit ERC1155\n else if (_collateralType == CollateralType.ERC1155) {\n bytes memory data;\n\n IERC1155Upgradeable(_collateralAddress).safeTransferFrom(\n _msgSender(),\n address(this),\n _tokenId,\n _amount,\n data\n );\n } else {\n revert(\"Invalid collateral type\");\n }\n }\n\n /**\n * @notice Internal function for transferring collateral assets out of this contract.\n * @param _collateral The collateral asset to withdraw.\n * @param _collateralAddress The address of the collateral contract.\n * @param _amount The amount to withdraw.\n * @param _recipient The address to send the assets to.\n */\n function _withdrawCollateral(\n Collateral memory _collateral,\n address _collateralAddress,\n uint256 _amount,\n address _recipient\n ) internal {\n // Withdraw ERC20\n if (_collateral._collateralType == CollateralType.ERC20) {\n IERC20Upgradeable(_collateralAddress).transfer(_recipient, _amount);\n }\n // Withdraw ERC721\n else if (_collateral._collateralType == CollateralType.ERC721) {\n require(_amount == 1, \"Incorrect withdrawal amount\");\n IERC721Upgradeable(_collateralAddress).transferFrom(\n address(this),\n _recipient,\n _collateral._tokenId\n );\n }\n // Withdraw ERC1155\n else if (_collateral._collateralType == CollateralType.ERC1155) {\n bytes memory data;\n\n IERC1155Upgradeable(_collateralAddress).safeTransferFrom(\n address(this),\n _recipient,\n _collateral._tokenId,\n _amount,\n data\n );\n } else {\n revert(\"Invalid collateral type\");\n }\n }\n\n // On NFT Received handlers\n\n function onERC721Received(address, address, uint256, bytes calldata)\n external\n pure\n returns (bytes4)\n {\n return\n bytes4(\n keccak256(\"onERC721Received(address,address,uint256,bytes)\")\n );\n }\n\n function onERC1155Received(\n address,\n address,\n uint256 id,\n uint256 value,\n bytes calldata\n ) external returns (bytes4) {\n return\n bytes4(\n keccak256(\n \"onERC1155Received(address,address,uint256,uint256,bytes)\"\n )\n );\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] calldata _ids,\n uint256[] calldata _values,\n bytes calldata\n ) external returns (bytes4) {\n require(\n _ids.length == 1,\n \"Only allowed one asset batch transfer per transaction.\"\n );\n return\n bytes4(\n keccak256(\n \"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"\n )\n );\n }\n}\n" + }, + "contracts/EscrowVault.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n/*\nAn escrow vault for repayments \n*/\n\n// Contracts\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\n\n// Interfaces\nimport \"./interfaces/IEscrowVault.sol\";\n\ncontract EscrowVault is Initializable, ContextUpgradeable, IEscrowVault {\n using SafeERC20 for ERC20;\n\n //account => token => balance\n mapping(address => mapping(address => uint256)) public balances;\n\n constructor() {}\n\n function initialize() external initializer {}\n\n /**\n * @notice Deposit tokens on behalf of another account\n * @param account The id for the loan to set.\n * @param token The address of the new active lender.\n */\n function deposit(address account, address token, uint256 amount)\n public\n override\n {\n uint256 balanceBefore = ERC20(token).balanceOf(address(this));\n ERC20(token).safeTransferFrom(_msgSender(), address(this), amount);\n uint256 balanceAfter = ERC20(token).balanceOf(address(this));\n\n balances[account][token] += balanceAfter - balanceBefore; //used for fee-on-transfer tokens\n }\n\n function withdraw(address token, uint256 amount) external {\n address account = _msgSender();\n\n balances[account][token] -= amount;\n ERC20(token).safeTransfer(account, amount);\n }\n}\n" + }, + "contracts/interfaces/aave/DataTypes.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nlibrary DataTypes {\n struct ReserveData {\n //stores the reserve configuration\n ReserveConfigurationMap configuration;\n //the liquidity index. Expressed in ray\n uint128 liquidityIndex;\n //the current supply rate. Expressed in ray\n uint128 currentLiquidityRate;\n //variable borrow index. Expressed in ray\n uint128 variableBorrowIndex;\n //the current variable borrow rate. Expressed in ray\n uint128 currentVariableBorrowRate;\n //the current stable borrow rate. Expressed in ray\n uint128 currentStableBorrowRate;\n //timestamp of last update\n uint40 lastUpdateTimestamp;\n //the id of the reserve. Represents the position in the list of the active reserves\n uint16 id;\n //aToken address\n address aTokenAddress;\n //stableDebtToken address\n address stableDebtTokenAddress;\n //variableDebtToken address\n address variableDebtTokenAddress;\n //address of the interest rate strategy\n address interestRateStrategyAddress;\n //the current treasury balance, scaled\n uint128 accruedToTreasury;\n //the outstanding unbacked aTokens minted through the bridging feature\n uint128 unbacked;\n //the outstanding debt borrowed against this asset in isolation mode\n uint128 isolationModeTotalDebt;\n }\n\n struct ReserveConfigurationMap {\n //bit 0-15: LTV\n //bit 16-31: Liq. threshold\n //bit 32-47: Liq. bonus\n //bit 48-55: Decimals\n //bit 56: reserve is active\n //bit 57: reserve is frozen\n //bit 58: borrowing is enabled\n //bit 59: stable rate borrowing enabled\n //bit 60: asset is paused\n //bit 61: borrowing in isolation mode is enabled\n //bit 62: siloed borrowing enabled\n //bit 63: flashloaning enabled\n //bit 64-79: reserve factor\n //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap\n //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap\n //bit 152-167 liquidation protocol fee\n //bit 168-175 eMode category\n //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled\n //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals\n //bit 252-255 unused\n\n uint256 data;\n }\n\n struct UserConfigurationMap {\n /**\n * @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset.\n * The first bit indicates if an asset is used as collateral by the user, the second whether an\n * asset is borrowed by the user.\n */\n uint256 data;\n }\n\n struct EModeCategory {\n // each eMode category has a custom ltv and liquidation threshold\n uint16 ltv;\n uint16 liquidationThreshold;\n uint16 liquidationBonus;\n // each eMode category may or may not have a custom oracle to override the individual assets price oracles\n address priceSource;\n string label;\n }\n\n enum InterestRateMode {\n NONE,\n STABLE,\n VARIABLE\n }\n\n struct ReserveCache {\n uint256 currScaledVariableDebt;\n uint256 nextScaledVariableDebt;\n uint256 currPrincipalStableDebt;\n uint256 currAvgStableBorrowRate;\n uint256 currTotalStableDebt;\n uint256 nextAvgStableBorrowRate;\n uint256 nextTotalStableDebt;\n uint256 currLiquidityIndex;\n uint256 nextLiquidityIndex;\n uint256 currVariableBorrowIndex;\n uint256 nextVariableBorrowIndex;\n uint256 currLiquidityRate;\n uint256 currVariableBorrowRate;\n uint256 reserveFactor;\n ReserveConfigurationMap reserveConfiguration;\n address aTokenAddress;\n address stableDebtTokenAddress;\n address variableDebtTokenAddress;\n uint40 reserveLastUpdateTimestamp;\n uint40 stableDebtLastUpdateTimestamp;\n }\n\n struct ExecuteLiquidationCallParams {\n uint256 reservesCount;\n uint256 debtToCover;\n address collateralAsset;\n address debtAsset;\n address user;\n bool receiveAToken;\n address priceOracle;\n uint8 userEModeCategory;\n address priceOracleSentinel;\n }\n\n struct ExecuteSupplyParams {\n address asset;\n uint256 amount;\n address onBehalfOf;\n uint16 referralCode;\n }\n\n struct ExecuteBorrowParams {\n address asset;\n address user;\n address onBehalfOf;\n uint256 amount;\n InterestRateMode interestRateMode;\n uint16 referralCode;\n bool releaseUnderlying;\n uint256 maxStableRateBorrowSizePercent;\n uint256 reservesCount;\n address oracle;\n uint8 userEModeCategory;\n address priceOracleSentinel;\n }\n\n struct ExecuteRepayParams {\n address asset;\n uint256 amount;\n InterestRateMode interestRateMode;\n address onBehalfOf;\n bool useATokens;\n }\n\n struct ExecuteWithdrawParams {\n address asset;\n uint256 amount;\n address to;\n uint256 reservesCount;\n address oracle;\n uint8 userEModeCategory;\n }\n\n struct ExecuteSetUserEModeParams {\n uint256 reservesCount;\n address oracle;\n uint8 categoryId;\n }\n\n struct FinalizeTransferParams {\n address asset;\n address from;\n address to;\n uint256 amount;\n uint256 balanceFromBefore;\n uint256 balanceToBefore;\n uint256 reservesCount;\n address oracle;\n uint8 fromEModeCategory;\n }\n\n struct FlashloanParams {\n address receiverAddress;\n address[] assets;\n uint256[] amounts;\n uint256[] interestRateModes;\n address onBehalfOf;\n bytes params;\n uint16 referralCode;\n uint256 flashLoanPremiumToProtocol;\n uint256 flashLoanPremiumTotal;\n uint256 maxStableRateBorrowSizePercent;\n uint256 reservesCount;\n address addressesProvider;\n uint8 userEModeCategory;\n bool isAuthorizedFlashBorrower;\n }\n\n struct FlashloanSimpleParams {\n address receiverAddress;\n address asset;\n uint256 amount;\n bytes params;\n uint16 referralCode;\n uint256 flashLoanPremiumToProtocol;\n uint256 flashLoanPremiumTotal;\n }\n\n struct FlashLoanRepaymentParams {\n uint256 amount;\n uint256 totalPremium;\n uint256 flashLoanPremiumToProtocol;\n address asset;\n address receiverAddress;\n uint16 referralCode;\n }\n\n struct CalculateUserAccountDataParams {\n UserConfigurationMap userConfig;\n uint256 reservesCount;\n address user;\n address oracle;\n uint8 userEModeCategory;\n }\n\n struct ValidateBorrowParams {\n ReserveCache reserveCache;\n UserConfigurationMap userConfig;\n address asset;\n address userAddress;\n uint256 amount;\n InterestRateMode interestRateMode;\n uint256 maxStableLoanPercent;\n uint256 reservesCount;\n address oracle;\n uint8 userEModeCategory;\n address priceOracleSentinel;\n bool isolationModeActive;\n address isolationModeCollateralAddress;\n uint256 isolationModeDebtCeiling;\n }\n\n struct ValidateLiquidationCallParams {\n ReserveCache debtReserveCache;\n uint256 totalDebt;\n uint256 healthFactor;\n address priceOracleSentinel;\n }\n\n struct CalculateInterestRatesParams {\n uint256 unbacked;\n uint256 liquidityAdded;\n uint256 liquidityTaken;\n uint256 totalStableDebt;\n uint256 totalVariableDebt;\n uint256 averageStableBorrowRate;\n uint256 reserveFactor;\n address reserve;\n address aToken;\n }\n\n struct InitReserveParams {\n address asset;\n address aTokenAddress;\n address stableDebtAddress;\n address variableDebtAddress;\n address interestRateStrategyAddress;\n uint16 reservesCount;\n uint16 maxNumberReserves;\n }\n}\n" + }, + "contracts/interfaces/aave/IFlashLoanSimpleReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.0;\n\nimport { IPoolAddressesProvider } from \"./IPoolAddressesProvider.sol\";\nimport { IPool } from \"./IPool.sol\";\n\n/**\n * @title IFlashLoanSimpleReceiver\n * @author Aave\n * @notice Defines the basic interface of a flashloan-receiver contract.\n * @dev Implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n */\ninterface IFlashLoanSimpleReceiver {\n /**\n * @notice Executes an operation after receiving the flash-borrowed asset\n * @dev Ensure that the contract can return the debt + premium, e.g., has\n * enough funds to repay and has approved the Pool to pull the total amount\n * @param asset The address of the flash-borrowed asset\n * @param amount The amount of the flash-borrowed asset\n * @param premium The fee of the flash-borrowed asset\n * @param initiator The address of the flashloan initiator\n * @param params The byte-encoded params passed when initiating the flashloan\n * @return True if the execution of the operation succeeds, false otherwise\n */\n function executeOperation(\n address asset,\n uint256 amount,\n uint256 premium,\n address initiator,\n bytes calldata params\n ) external returns (bool);\n\n function ADDRESSES_PROVIDER()\n external\n view\n returns (IPoolAddressesProvider);\n\n function POOL() external view returns (IPool);\n}\n" + }, + "contracts/interfaces/aave/IPool.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.0;\n\nimport { IPoolAddressesProvider } from \"./IPoolAddressesProvider.sol\";\nimport { DataTypes } from \"./DataTypes.sol\";\n\n/**\n * @title IPool\n * @author Aave\n * @notice Defines the basic interface for an Aave Pool.\n */\ninterface IPool {\n /**\n * @dev Emitted on mintUnbacked()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address initiating the supply\n * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens\n * @param amount The amount of supplied assets\n * @param referralCode The referral code used\n */\n event MintUnbacked(\n address indexed reserve,\n address user,\n address indexed onBehalfOf,\n uint256 amount,\n uint16 indexed referralCode\n );\n\n /**\n * @dev Emitted on backUnbacked()\n * @param reserve The address of the underlying asset of the reserve\n * @param backer The address paying for the backing\n * @param amount The amount added as backing\n * @param fee The amount paid in fees\n */\n event BackUnbacked(\n address indexed reserve,\n address indexed backer,\n uint256 amount,\n uint256 fee\n );\n\n /**\n * @dev Emitted on supply()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address initiating the supply\n * @param onBehalfOf The beneficiary of the supply, receiving the aTokens\n * @param amount The amount supplied\n * @param referralCode The referral code used\n */\n event Supply(\n address indexed reserve,\n address user,\n address indexed onBehalfOf,\n uint256 amount,\n uint16 indexed referralCode\n );\n\n /**\n * @dev Emitted on withdraw()\n * @param reserve The address of the underlying asset being withdrawn\n * @param user The address initiating the withdrawal, owner of aTokens\n * @param to The address that will receive the underlying\n * @param amount The amount to be withdrawn\n */\n event Withdraw(\n address indexed reserve,\n address indexed user,\n address indexed to,\n uint256 amount\n );\n\n /**\n * @dev Emitted on borrow() and flashLoan() when debt needs to be opened\n * @param reserve The address of the underlying asset being borrowed\n * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just\n * initiator of the transaction on flashLoan()\n * @param onBehalfOf The address that will be getting the debt\n * @param amount The amount borrowed out\n * @param interestRateMode The rate mode: 1 for Stable, 2 for Variable\n * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray\n * @param referralCode The referral code used\n */\n event Borrow(\n address indexed reserve,\n address user,\n address indexed onBehalfOf,\n uint256 amount,\n DataTypes.InterestRateMode interestRateMode,\n uint256 borrowRate,\n uint16 indexed referralCode\n );\n\n /**\n * @dev Emitted on repay()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The beneficiary of the repayment, getting his debt reduced\n * @param repayer The address of the user initiating the repay(), providing the funds\n * @param amount The amount repaid\n * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly\n */\n event Repay(\n address indexed reserve,\n address indexed user,\n address indexed repayer,\n uint256 amount,\n bool useATokens\n );\n\n /**\n * @dev Emitted on swapBorrowRateMode()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user swapping his rate mode\n * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable\n */\n event SwapBorrowRateMode(\n address indexed reserve,\n address indexed user,\n DataTypes.InterestRateMode interestRateMode\n );\n\n /**\n * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets\n * @param asset The address of the underlying asset of the reserve\n * @param totalDebt The total isolation mode debt for the reserve\n */\n event IsolationModeTotalDebtUpdated(\n address indexed asset,\n uint256 totalDebt\n );\n\n /**\n * @dev Emitted when the user selects a certain asset category for eMode\n * @param user The address of the user\n * @param categoryId The category id\n */\n event UserEModeSet(address indexed user, uint8 categoryId);\n\n /**\n * @dev Emitted on setUserUseReserveAsCollateral()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user enabling the usage as collateral\n */\n event ReserveUsedAsCollateralEnabled(\n address indexed reserve,\n address indexed user\n );\n\n /**\n * @dev Emitted on setUserUseReserveAsCollateral()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user enabling the usage as collateral\n */\n event ReserveUsedAsCollateralDisabled(\n address indexed reserve,\n address indexed user\n );\n\n /**\n * @dev Emitted on rebalanceStableBorrowRate()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user for which the rebalance has been executed\n */\n event RebalanceStableBorrowRate(\n address indexed reserve,\n address indexed user\n );\n\n /**\n * @dev Emitted on flashLoan()\n * @param target The address of the flash loan receiver contract\n * @param initiator The address initiating the flash loan\n * @param asset The address of the asset being flash borrowed\n * @param amount The amount flash borrowed\n * @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt\n * @param premium The fee flash borrowed\n * @param referralCode The referral code used\n */\n event FlashLoan(\n address indexed target,\n address initiator,\n address indexed asset,\n uint256 amount,\n DataTypes.InterestRateMode interestRateMode,\n uint256 premium,\n uint16 indexed referralCode\n );\n\n /**\n * @dev Emitted when a borrower is liquidated.\n * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\n * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\n * @param user The address of the borrower getting liquidated\n * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\n * @param liquidatedCollateralAmount The amount of collateral received by the liquidator\n * @param liquidator The address of the liquidator\n * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants\n * to receive the underlying collateral asset directly\n */\n event LiquidationCall(\n address indexed collateralAsset,\n address indexed debtAsset,\n address indexed user,\n uint256 debtToCover,\n uint256 liquidatedCollateralAmount,\n address liquidator,\n bool receiveAToken\n );\n\n /**\n * @dev Emitted when the state of a reserve is updated.\n * @param reserve The address of the underlying asset of the reserve\n * @param liquidityRate The next liquidity rate\n * @param stableBorrowRate The next stable borrow rate\n * @param variableBorrowRate The next variable borrow rate\n * @param liquidityIndex The next liquidity index\n * @param variableBorrowIndex The next variable borrow index\n */\n event ReserveDataUpdated(\n address indexed reserve,\n uint256 liquidityRate,\n uint256 stableBorrowRate,\n uint256 variableBorrowRate,\n uint256 liquidityIndex,\n uint256 variableBorrowIndex\n );\n\n /**\n * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.\n * @param reserve The address of the reserve\n * @param amountMinted The amount minted to the treasury\n */\n event MintedToTreasury(address indexed reserve, uint256 amountMinted);\n\n /**\n * @notice Mints an `amount` of aTokens to the `onBehalfOf`\n * @param asset The address of the underlying asset to mint\n * @param amount The amount to mint\n * @param onBehalfOf The address that will receive the aTokens\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function mintUnbacked(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @notice Back the current unbacked underlying with `amount` and pay `fee`.\n * @param asset The address of the underlying asset to back\n * @param amount The amount to back\n * @param fee The amount paid in fees\n * @return The backed amount\n */\n function backUnbacked(address asset, uint256 amount, uint256 fee)\n external\n returns (uint256);\n\n /**\n * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User supplies 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to supply\n * @param amount The amount to be supplied\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function supply(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @notice Supply with transfer approval of asset to be supplied done via permit function\n * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713\n * @param asset The address of the underlying asset to supply\n * @param amount The amount to be supplied\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param deadline The deadline timestamp that the permit is valid\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n * @param permitV The V parameter of ERC712 permit sig\n * @param permitR The R parameter of ERC712 permit sig\n * @param permitS The S parameter of ERC712 permit sig\n */\n function supplyWithPermit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode,\n uint256 deadline,\n uint8 permitV,\n bytes32 permitR,\n bytes32 permitS\n ) external;\n\n /**\n * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to The address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n */\n function withdraw(address asset, uint256 amount, address to)\n external\n returns (uint256);\n\n /**\n * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower\n * already supplied enough collateral, or he was given enough allowance by a credit delegator on the\n * corresponding debt token (StableDebtToken or VariableDebtToken)\n * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet\n * and 100 stable/variable debt tokens, depending on the `interestRateMode`\n * @param asset The address of the underlying asset to borrow\n * @param amount The amount to be borrowed\n * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable\n * @param referralCode The code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself\n * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator\n * if he has been given credit delegation allowance\n */\n function borrow(\n address asset,\n uint256 amount,\n uint256 interestRateMode,\n uint16 referralCode,\n address onBehalfOf\n ) external;\n\n /**\n * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned\n * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address\n * @param asset The address of the borrowed underlying asset previously borrowed\n * @param amount The amount to repay\n * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\n * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\n * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the\n * user calling the function if he wants to reduce/remove his own debt, or the address of any other\n * other borrower whose debt should be removed\n * @return The final amount repaid\n */\n function repay(\n address asset,\n uint256 amount,\n uint256 interestRateMode,\n address onBehalfOf\n ) external returns (uint256);\n\n /**\n * @notice Repay with transfer approval of asset to be repaid done via permit function\n * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713\n * @param asset The address of the borrowed underlying asset previously borrowed\n * @param amount The amount to repay\n * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\n * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\n * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the\n * user calling the function if he wants to reduce/remove his own debt, or the address of any other\n * other borrower whose debt should be removed\n * @param deadline The deadline timestamp that the permit is valid\n * @param permitV The V parameter of ERC712 permit sig\n * @param permitR The R parameter of ERC712 permit sig\n * @param permitS The S parameter of ERC712 permit sig\n * @return The final amount repaid\n */\n function repayWithPermit(\n address asset,\n uint256 amount,\n uint256 interestRateMode,\n address onBehalfOf,\n uint256 deadline,\n uint8 permitV,\n bytes32 permitR,\n bytes32 permitS\n ) external returns (uint256);\n\n /**\n * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the\n * equivalent debt tokens\n * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens\n * @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken\n * balance is not enough to cover the whole debt\n * @param asset The address of the borrowed underlying asset previously borrowed\n * @param amount The amount to repay\n * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\n * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\n * @return The final amount repaid\n */\n function repayWithATokens(\n address asset,\n uint256 amount,\n uint256 interestRateMode\n ) external returns (uint256);\n\n /**\n * @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa\n * @param asset The address of the underlying asset borrowed\n * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable\n */\n function swapBorrowRateMode(address asset, uint256 interestRateMode)\n external;\n\n /**\n * @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.\n * - Users can be rebalanced if the following conditions are satisfied:\n * 1. Usage ratio is above 95%\n * 2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too\n * much has been borrowed at a stable rate and suppliers are not earning enough\n * @param asset The address of the underlying asset borrowed\n * @param user The address of the user to be rebalanced\n */\n function rebalanceStableBorrowRate(address asset, address user) external;\n\n /**\n * @notice Allows suppliers to enable/disable a specific supplied asset as collateral\n * @param asset The address of the underlying asset supplied\n * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise\n */\n function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)\n external;\n\n /**\n * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1\n * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives\n * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk\n * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\n * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\n * @param user The address of the borrower getting liquidated\n * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\n * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants\n * to receive the underlying collateral asset directly\n */\n function liquidationCall(\n address collateralAsset,\n address debtAsset,\n address user,\n uint256 debtToCover,\n bool receiveAToken\n ) external;\n\n /**\n * @notice Allows smartcontracts to access the liquidity of the pool within one transaction,\n * as long as the amount taken plus a fee is returned.\n * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept\n * into consideration. For further details please visit https://docs.aave.com/developers/\n * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface\n * @param assets The addresses of the assets being flash-borrowed\n * @param amounts The amounts of the assets being flash-borrowed\n * @param interestRateModes Types of the debt to open if the flash loan is not returned:\n * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver\n * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\n * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\n * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2\n * @param params Variadic packed params to pass to the receiver as extra information\n * @param referralCode The code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function flashLoan(\n address receiverAddress,\n address[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata interestRateModes,\n address onBehalfOf,\n bytes calldata params,\n uint16 referralCode\n ) external;\n\n /**\n * @notice Allows smartcontracts to access the liquidity of the pool within one transaction,\n * as long as the amount taken plus a fee is returned.\n * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept\n * into consideration. For further details please visit https://docs.aave.com/developers/\n * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface\n * @param asset The address of the asset being flash-borrowed\n * @param amount The amount of the asset being flash-borrowed\n * @param params Variadic packed params to pass to the receiver as extra information\n * @param referralCode The code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function flashLoanSimple(\n address receiverAddress,\n address asset,\n uint256 amount,\n bytes calldata params,\n uint16 referralCode\n ) external;\n\n /**\n * @notice Returns the user account data across all the reserves\n * @param user The address of the user\n * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed\n * @return totalDebtBase The total debt of the user in the base currency used by the price feed\n * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed\n * @return currentLiquidationThreshold The liquidation threshold of the user\n * @return ltv The loan to value of The user\n * @return healthFactor The current health factor of the user\n */\n function getUserAccountData(address user)\n external\n view\n returns (\n uint256 totalCollateralBase,\n uint256 totalDebtBase,\n uint256 availableBorrowsBase,\n uint256 currentLiquidationThreshold,\n uint256 ltv,\n uint256 healthFactor\n );\n\n /**\n * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an\n * interest rate strategy\n * @dev Only callable by the PoolConfigurator contract\n * @param asset The address of the underlying asset of the reserve\n * @param aTokenAddress The address of the aToken that will be assigned to the reserve\n * @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve\n * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve\n * @param interestRateStrategyAddress The address of the interest rate strategy contract\n */\n function initReserve(\n address asset,\n address aTokenAddress,\n address stableDebtAddress,\n address variableDebtAddress,\n address interestRateStrategyAddress\n ) external;\n\n /**\n * @notice Drop a reserve\n * @dev Only callable by the PoolConfigurator contract\n * @param asset The address of the underlying asset of the reserve\n */\n function dropReserve(address asset) external;\n\n /**\n * @notice Updates the address of the interest rate strategy contract\n * @dev Only callable by the PoolConfigurator contract\n * @param asset The address of the underlying asset of the reserve\n * @param rateStrategyAddress The address of the interest rate strategy contract\n */\n function setReserveInterestRateStrategyAddress(\n address asset,\n address rateStrategyAddress\n ) external;\n\n /**\n * @notice Sets the configuration bitmap of the reserve as a whole\n * @dev Only callable by the PoolConfigurator contract\n * @param asset The address of the underlying asset of the reserve\n * @param configuration The new configuration bitmap\n */\n function setConfiguration(\n address asset,\n DataTypes.ReserveConfigurationMap calldata configuration\n ) external;\n\n /**\n * @notice Returns the configuration of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The configuration of the reserve\n */\n function getConfiguration(address asset)\n external\n view\n returns (DataTypes.ReserveConfigurationMap memory);\n\n /**\n * @notice Returns the configuration of the user across all the reserves\n * @param user The user address\n * @return The configuration of the user\n */\n function getUserConfiguration(address user)\n external\n view\n returns (DataTypes.UserConfigurationMap memory);\n\n /**\n * @notice Returns the normalized income of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The reserve's normalized income\n */\n function getReserveNormalizedIncome(address asset)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the normalized variable debt per unit of asset\n * @dev WARNING: This function is intended to be used primarily by the protocol itself to get a\n * \"dynamic\" variable index based on time, current stored index and virtual rate at the current\n * moment (approx. a borrower would get if opening a position). This means that is always used in\n * combination with variable debt supply/balances.\n * If using this function externally, consider that is possible to have an increasing normalized\n * variable debt that is not equivalent to how the variable debt index would be updated in storage\n * (e.g. only updates with non-zero variable debt supply)\n * @param asset The address of the underlying asset of the reserve\n * @return The reserve normalized variable debt\n */\n function getReserveNormalizedVariableDebt(address asset)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the state and configuration of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The state and configuration data of the reserve\n */\n function getReserveData(address asset)\n external\n view\n returns (DataTypes.ReserveData memory);\n\n /**\n * @notice Validates and finalizes an aToken transfer\n * @dev Only callable by the overlying aToken of the `asset`\n * @param asset The address of the underlying asset of the aToken\n * @param from The user from which the aTokens are transferred\n * @param to The user receiving the aTokens\n * @param amount The amount being transferred/withdrawn\n * @param balanceFromBefore The aToken balance of the `from` user before the transfer\n * @param balanceToBefore The aToken balance of the `to` user before the transfer\n */\n function finalizeTransfer(\n address asset,\n address from,\n address to,\n uint256 amount,\n uint256 balanceFromBefore,\n uint256 balanceToBefore\n ) external;\n\n /**\n * @notice Returns the list of the underlying assets of all the initialized reserves\n * @dev It does not include dropped reserves\n * @return The addresses of the underlying assets of the initialized reserves\n */\n function getReservesList() external view returns (address[] memory);\n\n /**\n * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct\n * @param id The id of the reserve as stored in the DataTypes.ReserveData struct\n * @return The address of the reserve associated with id\n */\n function getReserveAddressById(uint16 id) external view returns (address);\n\n /**\n * @notice Returns the PoolAddressesProvider connected to this contract\n * @return The address of the PoolAddressesProvider\n */\n function ADDRESSES_PROVIDER()\n external\n view\n returns (IPoolAddressesProvider);\n\n /**\n * @notice Updates the protocol fee on the bridging\n * @param bridgeProtocolFee The part of the premium sent to the protocol treasury\n */\n function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external;\n\n /**\n * @notice Updates flash loan premiums. Flash loan premium consists of two parts:\n * - A part is sent to aToken holders as extra, one time accumulated interest\n * - A part is collected by the protocol treasury\n * @dev The total premium is calculated on the total borrowed amount\n * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal`\n * @dev Only callable by the PoolConfigurator contract\n * @param flashLoanPremiumTotal The total premium, expressed in bps\n * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps\n */\n function updateFlashloanPremiums(\n uint128 flashLoanPremiumTotal,\n uint128 flashLoanPremiumToProtocol\n ) external;\n\n /**\n * @notice Configures a new category for the eMode.\n * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.\n * The category 0 is reserved as it's the default for volatile assets\n * @param id The id of the category\n * @param config The configuration of the category\n */\n function configureEModeCategory(\n uint8 id,\n DataTypes.EModeCategory memory config\n ) external;\n\n /**\n * @notice Returns the data of an eMode category\n * @param id The id of the category\n * @return The configuration data of the category\n */\n function getEModeCategoryData(uint8 id)\n external\n view\n returns (DataTypes.EModeCategory memory);\n\n /**\n * @notice Allows a user to use the protocol in eMode\n * @param categoryId The id of the category\n */\n function setUserEMode(uint8 categoryId) external;\n\n /**\n * @notice Returns the eMode the user is using\n * @param user The address of the user\n * @return The eMode id\n */\n function getUserEMode(address user) external view returns (uint256);\n\n /**\n * @notice Resets the isolation mode total debt of the given asset to zero\n * @dev It requires the given asset has zero debt ceiling\n * @param asset The address of the underlying asset to reset the isolationModeTotalDebt\n */\n function resetIsolationModeTotalDebt(address asset) external;\n\n /**\n * @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate\n * @return The percentage of available liquidity to borrow, expressed in bps\n */\n function MAX_STABLE_RATE_BORROW_SIZE_PERCENT()\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the total fee on flash loans\n * @return The total fee on flashloans\n */\n function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);\n\n /**\n * @notice Returns the part of the bridge fees sent to protocol\n * @return The bridge fee sent to the protocol treasury\n */\n function BRIDGE_PROTOCOL_FEE() external view returns (uint256);\n\n /**\n * @notice Returns the part of the flashloan fees sent to protocol\n * @return The flashloan fee sent to the protocol treasury\n */\n function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128);\n\n /**\n * @notice Returns the maximum number of reserves supported to be listed in this Pool\n * @return The maximum number of reserves supported\n */\n function MAX_NUMBER_RESERVES() external view returns (uint16);\n\n /**\n * @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens\n * @param assets The list of reserves for which the minting needs to be executed\n */\n function mintToTreasury(address[] calldata assets) external;\n\n /**\n * @notice Rescue and transfer tokens locked in this contract\n * @param token The address of the token\n * @param to The address of the recipient\n * @param amount The amount of token to transfer\n */\n function rescueTokens(address token, address to, uint256 amount) external;\n\n /**\n * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User supplies 100 USDC and gets in return 100 aUSDC\n * @dev Deprecated: Use the `supply` function instead\n * @param asset The address of the underlying asset to supply\n * @param amount The amount to be supplied\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n}\n" + }, + "contracts/interfaces/aave/IPoolAddressesProvider.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.0;\n\n/**\n * @title IPoolAddressesProvider\n * @author Aave\n * @notice Defines the basic interface for a Pool Addresses Provider.\n */\ninterface IPoolAddressesProvider {\n /**\n * @dev Emitted when the market identifier is updated.\n * @param oldMarketId The old id of the market\n * @param newMarketId The new id of the market\n */\n event MarketIdSet(string indexed oldMarketId, string indexed newMarketId);\n\n /**\n * @dev Emitted when the pool is updated.\n * @param oldAddress The old address of the Pool\n * @param newAddress The new address of the Pool\n */\n event PoolUpdated(address indexed oldAddress, address indexed newAddress);\n\n /**\n * @dev Emitted when the pool configurator is updated.\n * @param oldAddress The old address of the PoolConfigurator\n * @param newAddress The new address of the PoolConfigurator\n */\n event PoolConfiguratorUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the price oracle is updated.\n * @param oldAddress The old address of the PriceOracle\n * @param newAddress The new address of the PriceOracle\n */\n event PriceOracleUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the ACL manager is updated.\n * @param oldAddress The old address of the ACLManager\n * @param newAddress The new address of the ACLManager\n */\n event ACLManagerUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the ACL admin is updated.\n * @param oldAddress The old address of the ACLAdmin\n * @param newAddress The new address of the ACLAdmin\n */\n event ACLAdminUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the price oracle sentinel is updated.\n * @param oldAddress The old address of the PriceOracleSentinel\n * @param newAddress The new address of the PriceOracleSentinel\n */\n event PriceOracleSentinelUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the pool data provider is updated.\n * @param oldAddress The old address of the PoolDataProvider\n * @param newAddress The new address of the PoolDataProvider\n */\n event PoolDataProviderUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when a new proxy is created.\n * @param id The identifier of the proxy\n * @param proxyAddress The address of the created proxy contract\n * @param implementationAddress The address of the implementation contract\n */\n event ProxyCreated(\n bytes32 indexed id,\n address indexed proxyAddress,\n address indexed implementationAddress\n );\n\n /**\n * @dev Emitted when a new non-proxied contract address is registered.\n * @param id The identifier of the contract\n * @param oldAddress The address of the old contract\n * @param newAddress The address of the new contract\n */\n event AddressSet(\n bytes32 indexed id,\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the implementation of the proxy registered with id is updated\n * @param id The identifier of the contract\n * @param proxyAddress The address of the proxy contract\n * @param oldImplementationAddress The address of the old implementation contract\n * @param newImplementationAddress The address of the new implementation contract\n */\n event AddressSetAsProxy(\n bytes32 indexed id,\n address indexed proxyAddress,\n address oldImplementationAddress,\n address indexed newImplementationAddress\n );\n\n /**\n * @notice Returns the id of the Aave market to which this contract points to.\n * @return The market id\n */\n function getMarketId() external view returns (string memory);\n\n /**\n * @notice Associates an id with a specific PoolAddressesProvider.\n * @dev This can be used to create an onchain registry of PoolAddressesProviders to\n * identify and validate multiple Aave markets.\n * @param newMarketId The market id\n */\n function setMarketId(string calldata newMarketId) external;\n\n /**\n * @notice Returns an address by its identifier.\n * @dev The returned address might be an EOA or a contract, potentially proxied\n * @dev It returns ZERO if there is no registered address with the given id\n * @param id The id\n * @return The address of the registered for the specified id\n */\n function getAddress(bytes32 id) external view returns (address);\n\n /**\n * @notice General function to update the implementation of a proxy registered with\n * certain `id`. If there is no proxy registered, it will instantiate one and\n * set as implementation the `newImplementationAddress`.\n * @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit\n * setter function, in order to avoid unexpected consequences\n * @param id The id\n * @param newImplementationAddress The address of the new implementation\n */\n function setAddressAsProxy(bytes32 id, address newImplementationAddress)\n external;\n\n /**\n * @notice Sets an address for an id replacing the address saved in the addresses map.\n * @dev IMPORTANT Use this function carefully, as it will do a hard replacement\n * @param id The id\n * @param newAddress The address to set\n */\n function setAddress(bytes32 id, address newAddress) external;\n\n /**\n * @notice Returns the address of the Pool proxy.\n * @return The Pool proxy address\n */\n function getPool() external view returns (address);\n\n /**\n * @notice Updates the implementation of the Pool, or creates a proxy\n * setting the new `pool` implementation when the function is called for the first time.\n * @param newPoolImpl The new Pool implementation\n */\n function setPoolImpl(address newPoolImpl) external;\n\n /**\n * @notice Returns the address of the PoolConfigurator proxy.\n * @return The PoolConfigurator proxy address\n */\n function getPoolConfigurator() external view returns (address);\n\n /**\n * @notice Updates the implementation of the PoolConfigurator, or creates a proxy\n * setting the new `PoolConfigurator` implementation when the function is called for the first time.\n * @param newPoolConfiguratorImpl The new PoolConfigurator implementation\n */\n function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external;\n\n /**\n * @notice Returns the address of the price oracle.\n * @return The address of the PriceOracle\n */\n function getPriceOracle() external view returns (address);\n\n /**\n * @notice Updates the address of the price oracle.\n * @param newPriceOracle The address of the new PriceOracle\n */\n function setPriceOracle(address newPriceOracle) external;\n\n /**\n * @notice Returns the address of the ACL manager.\n * @return The address of the ACLManager\n */\n function getACLManager() external view returns (address);\n\n /**\n * @notice Updates the address of the ACL manager.\n * @param newAclManager The address of the new ACLManager\n */\n function setACLManager(address newAclManager) external;\n\n /**\n * @notice Returns the address of the ACL admin.\n * @return The address of the ACL admin\n */\n function getACLAdmin() external view returns (address);\n\n /**\n * @notice Updates the address of the ACL admin.\n * @param newAclAdmin The address of the new ACL admin\n */\n function setACLAdmin(address newAclAdmin) external;\n\n /**\n * @notice Returns the address of the price oracle sentinel.\n * @return The address of the PriceOracleSentinel\n */\n function getPriceOracleSentinel() external view returns (address);\n\n /**\n * @notice Updates the address of the price oracle sentinel.\n * @param newPriceOracleSentinel The address of the new PriceOracleSentinel\n */\n function setPriceOracleSentinel(address newPriceOracleSentinel) external;\n\n /**\n * @notice Returns the address of the data provider.\n * @return The address of the DataProvider\n */\n function getPoolDataProvider() external view returns (address);\n\n /**\n * @notice Updates the address of the data provider.\n * @param newDataProvider The address of the new DataProvider\n */\n function setPoolDataProvider(address newDataProvider) external;\n}\n" + }, + "contracts/interfaces/escrow/ICollateralEscrowV1.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nenum CollateralType {\n ERC20,\n ERC721,\n ERC1155\n}\n\nstruct Collateral {\n CollateralType _collateralType;\n uint256 _amount;\n uint256 _tokenId;\n address _collateralAddress;\n}\n\ninterface ICollateralEscrowV1 {\n /**\n * @notice Deposits a collateral asset into the escrow.\n * @param _collateralType The type of collateral asset to deposit (ERC721, ERC1155).\n * @param _collateralAddress The address of the collateral token.i feel\n * @param _amount The amount to deposit.\n */\n function depositAsset(\n CollateralType _collateralType,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId\n ) external payable;\n\n /**\n * @notice Withdraws a collateral asset from the escrow.\n * @param _collateralAddress The address of the collateral contract.\n * @param _amount The amount to withdraw.\n * @param _recipient The address to send the assets to.\n */\n function withdraw(\n address _collateralAddress,\n uint256 _amount,\n address _recipient\n ) external;\n\n function withdrawDustTokens( \n address _tokenAddress, \n uint256 _amount,\n address _recipient\n ) external;\n\n\n function getBid() external view returns (uint256);\n\n function initialize(uint256 _bidId) external;\n\n\n}\n" + }, + "contracts/interfaces/IASRegistry.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./IASResolver.sol\";\n\n/**\n * @title The global AS registry interface.\n */\ninterface IASRegistry {\n /**\n * @title A struct representing a record for a submitted AS (Attestation Schema).\n */\n struct ASRecord {\n // A unique identifier of the AS.\n bytes32 uuid;\n // Optional schema resolver.\n IASResolver resolver;\n // Auto-incrementing index for reference, assigned by the registry itself.\n uint256 index;\n // Custom specification of the AS (e.g., an ABI).\n bytes schema;\n }\n\n /**\n * @dev Triggered when a new AS has been registered\n *\n * @param uuid The AS UUID.\n * @param index The AS index.\n * @param schema The AS schema.\n * @param resolver An optional AS schema resolver.\n * @param attester The address of the account used to register the AS.\n */\n event Registered(\n bytes32 indexed uuid,\n uint256 indexed index,\n bytes schema,\n IASResolver resolver,\n address attester\n );\n\n /**\n * @dev Submits and reserve a new AS\n *\n * @param schema The AS data schema.\n * @param resolver An optional AS schema resolver.\n *\n * @return The UUID of the new AS.\n */\n function register(bytes calldata schema, IASResolver resolver)\n external\n returns (bytes32);\n\n /**\n * @dev Returns an existing AS by UUID\n *\n * @param uuid The UUID of the AS to retrieve.\n *\n * @return The AS data members.\n */\n function getAS(bytes32 uuid) external view returns (ASRecord memory);\n\n /**\n * @dev Returns the global counter for the total number of attestations\n *\n * @return The global counter for the total number of attestations.\n */\n function getASCount() external view returns (uint256);\n}\n" + }, + "contracts/interfaces/IASResolver.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n\n// SPDX-License-Identifier: MIT\n\n/**\n * @title The interface of an optional AS resolver.\n */\ninterface IASResolver {\n /**\n * @dev Returns whether the resolver supports ETH transfers\n */\n function isPayable() external pure returns (bool);\n\n /**\n * @dev Resolves an attestation and verifier whether its data conforms to the spec.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The AS data schema.\n * @param data The actual attestation data.\n * @param expirationTime The expiration time of the attestation.\n * @param msgSender The sender of the original attestation message.\n *\n * @return Whether the data is valid according to the scheme.\n */\n function resolve(\n address recipient,\n bytes calldata schema,\n bytes calldata data,\n uint256 expirationTime,\n address msgSender\n ) external payable returns (bool);\n}\n" + }, + "contracts/interfaces/ICollateralManager.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nimport { Collateral } from \"./escrow/ICollateralEscrowV1.sol\";\n\ninterface ICollateralManager {\n /**\n * @notice Checks the validity of a borrower's collateral balance.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral asset.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function commitCollateral(\n uint256 _bidId,\n Collateral[] calldata _collateralInfo\n ) external returns (bool validation_);\n\n /**\n * @notice Checks the validity of a borrower's collateral balance and commits it to a bid.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral asset.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function commitCollateral(\n uint256 _bidId,\n Collateral calldata _collateralInfo\n ) external returns (bool validation_);\n\n function checkBalances(\n address _borrowerAddress,\n Collateral[] calldata _collateralInfo\n ) external returns (bool validated_, bool[] memory checks_);\n\n /**\n * @notice Deploys a new collateral escrow.\n * @param _bidId The associated bidId of the collateral escrow.\n */\n function deployAndDeposit(uint256 _bidId) external;\n\n /**\n * @notice Gets the address of a deployed escrow.\n * @notice _bidId The bidId to return the escrow for.\n * @return The address of the escrow.\n */\n function getEscrow(uint256 _bidId) external view returns (address);\n\n /**\n * @notice Gets the collateral info for a given bid id.\n * @param _bidId The bidId to return the collateral info for.\n * @return The stored collateral info.\n */\n function getCollateralInfo(uint256 _bidId)\n external\n view\n returns (Collateral[] memory);\n\n function getCollateralAmount(uint256 _bidId, address collateralAssetAddress)\n external\n view\n returns (uint256 _amount);\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function withdraw(uint256 _bidId) external;\n\n /**\n * @notice Re-checks the validity of a borrower's collateral balance committed to a bid.\n * @param _bidId The id of the associated bid.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function revalidateCollateral(uint256 _bidId) external returns (bool);\n\n /**\n * @notice Sends the deposited collateral to a lender of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n */\n function lenderClaimCollateral(uint256 _bidId) external;\n\n\n\n /**\n * @notice Sends the deposited collateral to a lender of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n * @param _collateralRecipient the address that will receive the collateral \n */\n function lenderClaimCollateralWithRecipient(uint256 _bidId, address _collateralRecipient) external;\n\n\n /**\n * @notice Sends the deposited collateral to a liquidator of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n * @param _liquidatorAddress The address of the liquidator to send the collateral to.\n */\n function liquidateCollateral(uint256 _bidId, address _liquidatorAddress)\n external;\n}\n" + }, + "contracts/interfaces/ICommitmentRolloverLoan.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ICommitmentRolloverLoan {\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n }\n}\n" + }, + "contracts/interfaces/IEAS.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./IASRegistry.sol\";\nimport \"./IEASEIP712Verifier.sol\";\n\n/**\n * @title EAS - Ethereum Attestation Service interface\n */\ninterface IEAS {\n /**\n * @dev A struct representing a single attestation.\n */\n struct Attestation {\n // A unique identifier of the attestation.\n bytes32 uuid;\n // A unique identifier of the AS.\n bytes32 schema;\n // The recipient of the attestation.\n address recipient;\n // The attester/sender of the attestation.\n address attester;\n // The time when the attestation was created (Unix timestamp).\n uint256 time;\n // The time when the attestation expires (Unix timestamp).\n uint256 expirationTime;\n // The time when the attestation was revoked (Unix timestamp).\n uint256 revocationTime;\n // The UUID of the related attestation.\n bytes32 refUUID;\n // Custom attestation data.\n bytes data;\n }\n\n /**\n * @dev Triggered when an attestation has been made.\n *\n * @param recipient The recipient of the attestation.\n * @param attester The attesting account.\n * @param uuid The UUID the revoked attestation.\n * @param schema The UUID of the AS.\n */\n event Attested(\n address indexed recipient,\n address indexed attester,\n bytes32 uuid,\n bytes32 indexed schema\n );\n\n /**\n * @dev Triggered when an attestation has been revoked.\n *\n * @param recipient The recipient of the attestation.\n * @param attester The attesting account.\n * @param schema The UUID of the AS.\n * @param uuid The UUID the revoked attestation.\n */\n event Revoked(\n address indexed recipient,\n address indexed attester,\n bytes32 uuid,\n bytes32 indexed schema\n );\n\n /**\n * @dev Returns the address of the AS global registry.\n *\n * @return The address of the AS global registry.\n */\n function getASRegistry() external view returns (IASRegistry);\n\n /**\n * @dev Returns the address of the EIP712 verifier used to verify signed attestations.\n *\n * @return The address of the EIP712 verifier used to verify signed attestations.\n */\n function getEIP712Verifier() external view returns (IEASEIP712Verifier);\n\n /**\n * @dev Returns the global counter for the total number of attestations.\n *\n * @return The global counter for the total number of attestations.\n */\n function getAttestationsCount() external view returns (uint256);\n\n /**\n * @dev Attests to a specific AS.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param expirationTime The expiration time of the attestation.\n * @param refUUID An optional related attestation's UUID.\n * @param data Additional custom data.\n *\n * @return The UUID of the new attestation.\n */\n function attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data\n ) external payable returns (bytes32);\n\n /**\n * @dev Attests to a specific AS using a provided EIP712 signature.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param expirationTime The expiration time of the attestation.\n * @param refUUID An optional related attestation's UUID.\n * @param data Additional custom data.\n * @param attester The attesting account.\n * @param v The recovery ID.\n * @param r The x-coordinate of the nonce R.\n * @param s The signature data.\n *\n * @return The UUID of the new attestation.\n */\n function attestByDelegation(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external payable returns (bytes32);\n\n /**\n * @dev Revokes an existing attestation to a specific AS.\n *\n * @param uuid The UUID of the attestation to revoke.\n */\n function revoke(bytes32 uuid) external;\n\n /**\n * @dev Attests to a specific AS using a provided EIP712 signature.\n *\n * @param uuid The UUID of the attestation to revoke.\n * @param attester The attesting account.\n * @param v The recovery ID.\n * @param r The x-coordinate of the nonce R.\n * @param s The signature data.\n */\n function revokeByDelegation(\n bytes32 uuid,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns an existing attestation by UUID.\n *\n * @param uuid The UUID of the attestation to retrieve.\n *\n * @return The attestation data members.\n */\n function getAttestation(bytes32 uuid)\n external\n view\n returns (Attestation memory);\n\n /**\n * @dev Checks whether an attestation exists.\n *\n * @param uuid The UUID of the attestation to retrieve.\n *\n * @return Whether an attestation exists.\n */\n function isAttestationValid(bytes32 uuid) external view returns (bool);\n\n /**\n * @dev Checks whether an attestation is active.\n *\n * @param uuid The UUID of the attestation to retrieve.\n *\n * @return Whether an attestation is active.\n */\n function isAttestationActive(bytes32 uuid) external view returns (bool);\n\n /**\n * @dev Returns all received attestation UUIDs.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function getReceivedAttestationUUIDs(\n address recipient,\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view returns (bytes32[] memory);\n\n /**\n * @dev Returns the number of received attestation UUIDs.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n *\n * @return The number of attestations.\n */\n function getReceivedAttestationUUIDsCount(address recipient, bytes32 schema)\n external\n view\n returns (uint256);\n\n /**\n * @dev Returns all sent attestation UUIDs.\n *\n * @param attester The attesting account.\n * @param schema The UUID of the AS.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function getSentAttestationUUIDs(\n address attester,\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view returns (bytes32[] memory);\n\n /**\n * @dev Returns the number of sent attestation UUIDs.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n *\n * @return The number of attestations.\n */\n function getSentAttestationUUIDsCount(address recipient, bytes32 schema)\n external\n view\n returns (uint256);\n\n /**\n * @dev Returns all attestations related to a specific attestation.\n *\n * @param uuid The UUID of the attestation to retrieve.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function getRelatedAttestationUUIDs(\n bytes32 uuid,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view returns (bytes32[] memory);\n\n /**\n * @dev Returns the number of related attestation UUIDs.\n *\n * @param uuid The UUID of the attestation to retrieve.\n *\n * @return The number of related attestations.\n */\n function getRelatedAttestationUUIDsCount(bytes32 uuid)\n external\n view\n returns (uint256);\n\n /**\n * @dev Returns all per-schema attestation UUIDs.\n *\n * @param schema The UUID of the AS.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function getSchemaAttestationUUIDs(\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view returns (bytes32[] memory);\n\n /**\n * @dev Returns the number of per-schema attestation UUIDs.\n *\n * @param schema The UUID of the AS.\n *\n * @return The number of attestations.\n */\n function getSchemaAttestationUUIDsCount(bytes32 schema)\n external\n view\n returns (uint256);\n}\n" + }, + "contracts/interfaces/IEASEIP712Verifier.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n\n// SPDX-License-Identifier: MIT\n\n/**\n * @title EIP712 typed signatures verifier for EAS delegated attestations interface.\n */\ninterface IEASEIP712Verifier {\n /**\n * @dev Returns the current nonce per-account.\n *\n * @param account The requested accunt.\n *\n * @return The current nonce.\n */\n function getNonce(address account) external view returns (uint256);\n\n /**\n * @dev Verifies signed attestation.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param expirationTime The expiration time of the attestation.\n * @param refUUID An optional related attestation's UUID.\n * @param data Additional custom data.\n * @param attester The attesting account.\n * @param v The recovery ID.\n * @param r The x-coordinate of the nonce R.\n * @param s The signature data.\n */\n function attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Verifies signed revocations.\n *\n * @param uuid The UUID of the attestation to revoke.\n * @param attester The attesting account.\n * @param v The recovery ID.\n * @param r The x-coordinate of the nonce R.\n * @param s The signature data.\n */\n function revoke(\n bytes32 uuid,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "contracts/interfaces/IEscrowVault.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface IEscrowVault {\n /**\n * @notice Deposit tokens on behalf of another account\n * @param account The address of the account\n * @param token The address of the token\n * @param amount The amount to increase the balance\n */\n function deposit(address account, address token, uint256 amount) external;\n\n function withdraw(address token, uint256 amount) external ;\n}\n" + }, + "contracts/interfaces/IExtensionsContext.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IExtensionsContext {\n function hasExtension(address extension, address account)\n external\n view\n returns (bool);\n\n function addExtension(address extension) external;\n\n function revokeExtension(address extension) external;\n}\n" + }, + "contracts/interfaces/IFlashRolloverLoan_G4.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IFlashRolloverLoan_G4 {\n struct RolloverCallbackArgs {\n address lenderCommitmentForwarder;\n uint256 loanId;\n address borrower;\n uint256 borrowerAmount;\n bytes acceptCommitmentArgs;\n }\n}\n" + }, + "contracts/interfaces/IFlashRolloverLoan_G6.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IFlashRolloverLoan_G6 {\n struct RolloverCallbackArgs {\n address lenderCommitmentForwarder;\n uint256 loanId;\n address borrower;\n uint256 borrowerAmount;\n address rewardRecipient;\n uint256 rewardAmount;\n bytes acceptCommitmentArgs;\n }\n}\n" + }, + "contracts/interfaces/IFlashRolloverLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IFlashRolloverLoan {\n struct RolloverCallbackArgs { \n uint256 loanId;\n address borrower;\n uint256 borrowerAmount;\n bytes acceptCommitmentArgs;\n }\n}\n" + }, + "contracts/interfaces/IHasProtocolPausingManager.sol": { + "content": "\n\n\n\n\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\n//records the unpause timestamp s\ninterface IHasProtocolPausingManager {\n \n \n function getProtocolPausingManager() external view returns (address); \n\n // function isPauser(address _address) external view returns (bool); \n\n\n}\n" + }, + "contracts/interfaces/ILenderCommitmentForwarder_U1.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ILenderCommitmentForwarder_U1 {\n enum CommitmentCollateralType {\n NONE, // no collateral required\n ERC20,\n ERC721,\n ERC1155,\n ERC721_ANY_ID,\n ERC1155_ANY_ID,\n ERC721_MERKLE_PROOF,\n ERC1155_MERKLE_PROOF\n }\n\n /**\n * @notice Details about a lender's capital commitment.\n * @param maxPrincipal Amount of tokens being committed by the lender. Max amount that can be loaned.\n * @param expiration Expiration time in seconds, when the commitment expires.\n * @param maxDuration Length of time, in seconds that the lender's capital can be lent out for.\n * @param minInterestRate Minimum Annual percentage to be applied for loans using the lender's capital.\n * @param collateralTokenAddress The address for the token contract that must be used to provide collateral for loans for this commitment.\n * @param maxPrincipalPerCollateralAmount The amount of principal that can be used for a loan per each unit of collateral, expanded additionally by principal decimals.\n * @param collateralTokenType The type of asset of the collateralTokenAddress (ERC20, ERC721, or ERC1155).\n * @param lender The address of the lender for this commitment.\n * @param marketId The market id for this commitment.\n * @param principalTokenAddress The address for the token contract that will be used to provide principal for loans of this commitment.\n */\n struct Commitment {\n uint256 maxPrincipal;\n uint32 expiration;\n uint32 maxDuration;\n uint16 minInterestRate;\n address collateralTokenAddress;\n uint256 collateralTokenId; //we use this for the MerkleRootHash for type ERC721_MERKLE_PROOF\n uint256 maxPrincipalPerCollateralAmount;\n CommitmentCollateralType collateralTokenType;\n address lender;\n uint256 marketId;\n address principalTokenAddress;\n }\n\n struct PoolRouteConfig {\n address pool;\n bool zeroForOne;\n uint32 twapInterval;\n uint256 token0Decimals;\n uint256 token1Decimals;\n }\n\n // mapping(uint256 => Commitment) public commitments;\n\n function getCommitmentMarketId(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function getCommitmentLender(uint256 _commitmentId)\n external\n view\n returns (address);\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function createCommitmentWithUniswap(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList,\n PoolRouteConfig[] calldata _poolRoutes,\n uint16 _poolOracleLtvRatio\n ) external returns (uint256);\n\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) external returns (uint256 bidId_);\n\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) external returns (uint256 bidId_);\n\n\n function getCommitmentPrincipalTokenAddress(uint256 _commitmentId)\n external\n view\n returns (address);\n\n function getCommitmentCollateralTokenAddress(uint256 _commitmentId)\n external\n view\n returns (address);\n\n\n}\n" + }, + "contracts/interfaces/ILenderCommitmentForwarder.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ILenderCommitmentForwarder {\n enum CommitmentCollateralType {\n NONE, // no collateral required\n ERC20,\n ERC721,\n ERC1155,\n ERC721_ANY_ID,\n ERC1155_ANY_ID,\n ERC721_MERKLE_PROOF,\n ERC1155_MERKLE_PROOF\n }\n\n /**\n * @notice Details about a lender's capital commitment.\n * @param maxPrincipal Amount of tokens being committed by the lender. Max amount that can be loaned.\n * @param expiration Expiration time in seconds, when the commitment expires.\n * @param maxDuration Length of time, in seconds that the lender's capital can be lent out for.\n * @param minInterestRate Minimum Annual percentage to be applied for loans using the lender's capital.\n * @param collateralTokenAddress The address for the token contract that must be used to provide collateral for loans for this commitment.\n * @param maxPrincipalPerCollateralAmount The amount of principal that can be used for a loan per each unit of collateral, expanded additionally by principal decimals.\n * @param collateralTokenType The type of asset of the collateralTokenAddress (ERC20, ERC721, or ERC1155).\n * @param lender The address of the lender for this commitment.\n * @param marketId The market id for this commitment.\n * @param principalTokenAddress The address for the token contract that will be used to provide principal for loans of this commitment.\n */\n struct Commitment {\n uint256 maxPrincipal;\n uint32 expiration;\n uint32 maxDuration;\n uint16 minInterestRate;\n address collateralTokenAddress;\n uint256 collateralTokenId; //we use this for the MerkleRootHash for type ERC721_MERKLE_PROOF\n uint256 maxPrincipalPerCollateralAmount;\n CommitmentCollateralType collateralTokenType;\n address lender;\n uint256 marketId;\n address principalTokenAddress;\n }\n\n // mapping(uint256 => Commitment) public commitments;\n\n function getCommitmentMarketId(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function getCommitmentLender(uint256 _commitmentId)\n external\n view\n returns (address);\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function createCommitment(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList\n ) external returns (uint256);\n\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) external returns (uint256 bidId_);\n \n\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) external returns (uint256 bidId_);\n}\n" + }, + "contracts/interfaces/ILenderCommitmentGroup.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\nimport {IUniswapPricingLibrary} from \"../interfaces/IUniswapPricingLibrary.sol\";\ninterface ILenderCommitmentGroup {\n\n\n\n struct CommitmentGroupConfig {\n address principalTokenAddress;\n address collateralTokenAddress;\n uint256 marketId;\n uint32 maxLoanDuration;\n uint16 interestRateLowerBound;\n uint16 interestRateUpperBound;\n uint16 liquidityThresholdPercent;\n uint16 collateralRatio; //essentially the overcollateralization ratio. 10000 is 1:1 baseline ?\n \n }\n\n\n function initialize(\n CommitmentGroupConfig calldata _commitmentGroupConfig,\n IUniswapPricingLibrary.PoolRouteConfig[] calldata _poolOracleRoutes \n )\n external\n returns (\n //uint256 _maxPrincipalPerCollateralAmount //use oracle instead\n\n //ILenderCommitmentForwarder.Commitment calldata _createCommitmentArgs\n\n address poolSharesToken\n );\n\n function addPrincipalToCommitmentGroup(\n uint256 _amount,\n address _sharesRecipient,\n uint256 _minAmountOut\n ) external returns (uint256 sharesAmount_);\n\n\n function getTokenDifferenceFromLiquidations() external view returns (int256);\n\n}\n" + }, + "contracts/interfaces/ILenderManager.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n\n// SPDX-License-Identifier: MIT\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\n\nabstract contract ILenderManager is IERC721Upgradeable {\n /**\n * @notice Registers a new active lender for a loan, minting the nft.\n * @param _bidId The id for the loan to set.\n * @param _newLender The address of the new active lender.\n */\n function registerLoan(uint256 _bidId, address _newLender) external virtual;\n}\n" + }, + "contracts/interfaces/ILoanRepaymentCallbacks.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\n//tellerv2 should support this\ninterface ILoanRepaymentCallbacks {\n function setRepaymentListenerForBid(uint256 _bidId, address _listener)\n external;\n\n function getRepaymentListenerForBid(uint256 _bidId)\n external\n view\n returns (address);\n}\n" + }, + "contracts/interfaces/ILoanRepaymentListener.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ILoanRepaymentListener {\n function repayLoanCallback(\n uint256 bidId,\n address repayer,\n uint256 principalAmount,\n uint256 interestAmount\n ) external;\n}\n" + }, + "contracts/interfaces/IMarketLiquidityRewards.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IMarketLiquidityRewards {\n struct RewardAllocation {\n address allocator;\n address rewardTokenAddress;\n uint256 rewardTokenAmount;\n uint256 marketId;\n //requirements for loan\n address requiredPrincipalTokenAddress; //0 for any\n address requiredCollateralTokenAddress; //0 for any -- could be an enumerable set?\n uint256 minimumCollateralPerPrincipalAmount;\n uint256 rewardPerLoanPrincipalAmount;\n uint32 bidStartTimeMin;\n uint32 bidStartTimeMax;\n AllocationStrategy allocationStrategy;\n }\n\n enum AllocationStrategy {\n BORROWER,\n LENDER\n }\n\n function allocateRewards(RewardAllocation calldata _allocation)\n external\n returns (uint256 allocationId_);\n\n function increaseAllocationAmount(\n uint256 _allocationId,\n uint256 _tokenAmount\n ) external;\n\n function deallocateRewards(uint256 _allocationId, uint256 _amount) external;\n\n function claimRewards(uint256 _allocationId, uint256 _bidId) external;\n\n function rewardClaimedForBid(uint256 _bidId, uint256 _allocationId)\n external\n view\n returns (bool);\n\n function getRewardTokenAmount(uint256 _allocationId)\n external\n view\n returns (uint256);\n\n function initialize() external;\n}\n" + }, + "contracts/interfaces/IMarketRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../EAS/TellerAS.sol\";\nimport { PaymentType, PaymentCycleType } from \"../libraries/V2Calculations.sol\";\n\ninterface IMarketRegistry {\n function initialize(TellerAS tellerAs) external;\n\n function isVerifiedLender(uint256 _marketId, address _lender)\n external\n view\n returns (bool, bytes32);\n\n function isMarketOpen(uint256 _marketId) external view returns (bool);\n\n function isMarketClosed(uint256 _marketId) external view returns (bool);\n\n function isVerifiedBorrower(uint256 _marketId, address _borrower)\n external\n view\n returns (bool, bytes32);\n\n function getMarketOwner(uint256 _marketId) external view returns (address);\n\n function getMarketFeeRecipient(uint256 _marketId)\n external\n view\n returns (address);\n\n function getMarketURI(uint256 _marketId)\n external\n view\n returns (string memory);\n\n function getPaymentCycle(uint256 _marketId)\n external\n view\n returns (uint32, PaymentCycleType);\n\n function getPaymentDefaultDuration(uint256 _marketId)\n external\n view\n returns (uint32);\n\n function getBidExpirationTime(uint256 _marketId)\n external\n view\n returns (uint32);\n\n function getMarketplaceFee(uint256 _marketId)\n external\n view\n returns (uint16);\n\n function getPaymentType(uint256 _marketId)\n external\n view\n returns (PaymentType);\n\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n PaymentType _paymentType,\n PaymentCycleType _paymentCycleType,\n string calldata _uri\n ) external returns (uint256 marketId_);\n\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n string calldata _uri\n ) external returns (uint256 marketId_);\n\n function closeMarket(uint256 _marketId) external;\n}\n" + }, + "contracts/interfaces/IPausableTimestamp.sol": { + "content": "\n\n\n\n\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\n//records the unpause timestamp s\ninterface IPausableTimestamp {\n \n \n function getLastUnpausedAt() \n external view \n returns (uint256) ;\n\n // function setLastUnpausedAt() internal;\n\n\n\n}\n" + }, + "contracts/interfaces/IProtocolFee.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IProtocolFee {\n function protocolFee() external view returns (uint16);\n}\n" + }, + "contracts/interfaces/IProtocolPausingManager.sol": { + "content": "\n\n\n\n\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\n//records the unpause timestamp s\ninterface IProtocolPausingManager {\n \n function isPauser(address _address) external view returns (bool);\n function protocolPaused() external view returns (bool);\n function liquidationsPaused() external view returns (bool);\n \n \n\n}\n" + }, + "contracts/interfaces/IReputationManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nenum RepMark {\n Good,\n Delinquent,\n Default\n}\n\ninterface IReputationManager {\n function initialize(address protocolAddress) external;\n\n function getDelinquentLoanIds(address _account)\n external\n returns (uint256[] memory);\n\n function getDefaultedLoanIds(address _account)\n external\n returns (uint256[] memory);\n\n function getCurrentDelinquentLoanIds(address _account)\n external\n returns (uint256[] memory);\n\n function getCurrentDefaultLoanIds(address _account)\n external\n returns (uint256[] memory);\n\n function updateAccountReputation(address _account) external;\n\n function updateAccountReputation(address _account, uint256 _bidId)\n external\n returns (RepMark);\n}\n" + }, + "contracts/interfaces/ISmartCommitment.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nenum CommitmentCollateralType {\n NONE, // no collateral required\n ERC20,\n ERC721,\n ERC1155,\n ERC721_ANY_ID,\n ERC1155_ANY_ID,\n ERC721_MERKLE_PROOF,\n ERC1155_MERKLE_PROOF\n}\n\ninterface ISmartCommitment {\n function getPrincipalTokenAddress() external view returns (address);\n\n function getMarketId() external view returns (uint256);\n\n function getCollateralTokenAddress() external view returns (address);\n\n function getCollateralTokenType()\n external\n view\n returns (CommitmentCollateralType);\n\n function getCollateralTokenId() external view returns (uint256);\n\n function getMinInterestRate(uint256 _delta) external view returns (uint16);\n\n function getMaxLoanDuration() external view returns (uint32);\n\n function getPrincipalAmountAvailableToBorrow()\n external\n view\n returns (uint256);\n\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount\n \n )\n external\n view\n returns (uint256);\n\n \n function acceptFundsForAcceptBid(\n address _borrower,\n uint256 _bidId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n address _collateralTokenAddress,\n uint256 _collateralTokenId,\n uint32 _loanDuration,\n uint16 _interestRate\n ) external;\n}\n" + }, + "contracts/interfaces/ISmartCommitmentForwarder.sol": { + "content": "\n\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ISmartCommitmentForwarder {\n \n function acceptSmartCommitmentWithRecipient(\n address _smartCommitmentAddress,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) external returns (uint256 bidId) ;\n\n\n function setLiquidationProtocolFeePercent(uint256 _percent) \n external;\n\n function getLiquidationProtocolFeePercent() \n external view returns (uint256) ;\n\n\n\n}" + }, + "contracts/interfaces/ITellerV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Payment, BidState } from \"../TellerV2Storage.sol\";\nimport { Collateral } from \"./escrow/ICollateralEscrowV1.sol\";\n\ninterface ITellerV2 {\n /**\n * @notice Function for a borrower to create a bid for a loan.\n * @param _lendingToken The lending token asset requested to be borrowed.\n * @param _marketplaceId The unique id of the marketplace for the bid.\n * @param _principal The principal amount of the loan bid.\n * @param _duration The recurrent length of time before which a payment is due.\n * @param _APR The proposed interest rate for the loan bid.\n * @param _metadataURI The URI for additional borrower loan information as part of loan bid.\n * @param _receiver The address where the loan amount will be sent to.\n */\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver\n ) external returns (uint256 bidId_);\n\n /**\n * @notice Function for a borrower to create a bid for a loan with Collateral.\n * @param _lendingToken The lending token asset requested to be borrowed.\n * @param _marketplaceId The unique id of the marketplace for the bid.\n * @param _principal The principal amount of the loan bid.\n * @param _duration The recurrent length of time before which a payment is due.\n * @param _APR The proposed interest rate for the loan bid.\n * @param _metadataURI The URI for additional borrower loan information as part of loan bid.\n * @param _receiver The address where the loan amount will be sent to.\n * @param _collateralInfo Additional information about the collateral asset.\n */\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver,\n Collateral[] calldata _collateralInfo\n ) external returns (uint256 bidId_);\n\n /**\n * @notice Function for a lender to accept a proposed loan bid.\n * @param _bidId The id of the loan bid to accept.\n */\n function lenderAcceptBid(uint256 _bidId)\n external\n returns (\n uint256 amountToProtocol,\n uint256 amountToMarketplace,\n uint256 amountToBorrower\n );\n\n /**\n * @notice Function for users to make the minimum amount due for an active loan.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanMinimum(uint256 _bidId) external;\n\n /**\n * @notice Function for users to repay an active loan in full.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanFull(uint256 _bidId) external;\n\n /**\n * @notice Function for users to make a payment towards an active loan.\n * @param _bidId The id of the loan to make the payment towards.\n * @param _amount The amount of the payment.\n */\n function repayLoan(uint256 _bidId, uint256 _amount) external;\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n */\n function isLoanDefaulted(uint256 _bidId) external view returns (bool);\n\n /**\n * @notice Checks to see if a loan was delinquent for longer than liquidation delay.\n * @param _bidId The id of the loan bid to check for.\n */\n function isLoanLiquidateable(uint256 _bidId) external view returns (bool);\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n */\n function isPaymentLate(uint256 _bidId) external view returns (bool);\n\n function getBidState(uint256 _bidId) external view returns (BidState);\n\n function getBorrowerActiveLoanIds(address _borrower)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @notice Returns the borrower address for a given bid.\n * @param _bidId The id of the bid/loan to get the borrower for.\n * @return borrower_ The address of the borrower associated with the bid.\n */\n function getLoanBorrower(uint256 _bidId)\n external\n view\n returns (address borrower_);\n\n /**\n * @notice Returns the lender address for a given bid.\n * @param _bidId The id of the bid/loan to get the lender for.\n * @return lender_ The address of the lender associated with the bid.\n */\n function getLoanLender(uint256 _bidId)\n external\n view\n returns (address lender_);\n\n function getLoanLendingToken(uint256 _bidId)\n external\n view\n returns (address token_);\n\n function getLoanMarketId(uint256 _bidId) external view returns (uint256);\n\n function getLoanSummary(uint256 _bidId)\n external\n view\n returns (\n address borrower,\n address lender,\n uint256 marketId,\n address principalTokenAddress,\n uint256 principalAmount,\n uint32 acceptedTimestamp,\n uint32 lastRepaidTimestamp,\n BidState bidState\n );\n\n function calculateAmountOwed(uint256 _bidId, uint256 _timestamp)\n external\n view\n returns (Payment memory owed);\n\n function calculateAmountDue(uint256 _bidId, uint256 _timestamp)\n external\n view\n returns (Payment memory due);\n\n function lenderCloseLoan(uint256 _bidId) external;\n\n function lenderCloseLoanWithRecipient(uint256 _bidId, address _recipient)\n external;\n\n function liquidateLoanFull(uint256 _bidId) external;\n\n function liquidateLoanFullWithRecipient(uint256 _bidId, address _recipient)\n external;\n\n function getLoanDefaultTimestamp(uint256 _bidId)\n external\n view\n returns (uint256);\n\n\n function getEscrowVault() external view returns(address);\n\n\n // function isPauser(address _account) external view returns(bool);\n}\n" + }, + "contracts/interfaces/ITellerV2Autopay.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ITellerV2Autopay {\n function setAutoPayEnabled(uint256 _bidId, bool _autoPayEnabled) external;\n\n function autoPayLoanMinimum(uint256 _bidId) external;\n\n function initialize(uint16 _newFee, address _newOwner) external;\n\n function setAutopayFee(uint16 _newFee) external;\n}\n" + }, + "contracts/interfaces/ITellerV2Context.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ITellerV2Context {\n function setTrustedMarketForwarder(uint256 _marketId, address _forwarder)\n external;\n\n function approveMarketForwarder(uint256 _marketId, address _forwarder)\n external;\n}\n" + }, + "contracts/interfaces/ITellerV2MarketForwarder.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nimport { Collateral } from \"./escrow/ICollateralEscrowV1.sol\";\n\ninterface ITellerV2MarketForwarder {\n struct CreateLoanArgs {\n uint256 marketId;\n address lendingToken;\n uint256 principal;\n uint32 duration;\n uint16 interestRate;\n string metadataURI;\n address recipient;\n Collateral[] collateral;\n }\n}\n" + }, + "contracts/interfaces/ITellerV2Storage.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ITellerV2Storage {\n function marketRegistry() external view returns (address);\n}\n" + }, + "contracts/interfaces/IUniswapPricingLibrary.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface IUniswapPricingLibrary {\n \n\n struct PoolRouteConfig {\n address pool;\n bool zeroForOne;\n uint32 twapInterval;\n uint256 token0Decimals;\n uint256 token1Decimals;\n } \n\n\n\n function getUniswapPriceRatioForPoolRoutes(\n PoolRouteConfig[] memory poolRoutes\n ) external view returns (uint256 priceRatio);\n\n\n function getUniswapPriceRatioForPool(\n PoolRouteConfig memory poolRoute\n ) external view returns (uint256 priceRatio);\n\n}\n" + }, + "contracts/interfaces/IUniswapV2Router.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n @notice This interface defines the different functions available for a UniswapV2Router.\n @author develop@teller.finance\n */\ninterface IUniswapV2Router {\n function factory() external pure returns (address);\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);\n\n function addLiquidityETH(\n address token,\n uint256 amountTokenDesired,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n )\n external\n payable\n returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);\n\n function removeLiquidity(\n address tokenA,\n address tokenB,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) external returns (uint256 amountA, uint256 amountB);\n\n function removeLiquidityETH(\n address token,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline\n ) external returns (uint256 amountToken, uint256 amountETH);\n\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountA, uint256 amountB);\n\n function removeLiquidityETHWithPermit(\n address token,\n uint256 liquidity,\n uint256 amountTokenMin,\n uint256 amountETHMin,\n address to,\n uint256 deadline,\n bool approveMax,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external returns (uint256 amountToken, uint256 amountETH);\n\n function quote(uint256 amountA, uint256 reserveA, uint256 reserveB)\n external\n pure\n returns (uint256 amountB);\n\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) external pure returns (uint256 amountOut);\n\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) external pure returns (uint256 amountIn);\n\n function getAmountsOut(uint256 amountIn, address[] calldata path)\n external\n view\n returns (uint256[] memory amounts);\n\n function getAmountsIn(uint256 amountOut, address[] calldata path)\n external\n view\n returns (uint256[] memory amounts);\n\n /**\n @notice It returns the address of the canonical WETH address;\n */\n function WETH() external pure returns (address);\n\n /**\n @notice Swaps an exact amount of input tokens for as many output tokens as possible, along the route determined by the path. The first element of path is the input token, the last is the output token, and any intermediate elements represent intermediate pairs to trade through (if, for example, a direct pair does not exist).\n @param amountIn The amount of input tokens to send.\n @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n @param path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.\n @param to Recipient of the output tokens.\n @param deadline Unix timestamp after which the transaction will revert.\n @return amounts The input token amount and all subsequent output token amounts.\n @dev msg.sender should have already given the router an allowance of at least amountIn on the input token.\n */\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n /**\n @notice Swaps an exact amount of tokens for as much ETH as possible, along the route determined by the path. The first element of path is the input token, the last must be WETH, and any intermediate elements represent intermediate pairs to trade through (if, for example, a direct pair does not exist).\n @param amountIn The amount of input tokens to send.\n @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n @param path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.\n @param to Recipient of the ETH.\n @param deadline Unix timestamp after which the transaction will revert.\n @return amounts The input token amount and all subsequent output token amounts.\n @dev If the to address is a smart contract, it must have the ability to receive ETH.\n */\n function swapExactTokensForETH(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n /**\n @notice Swaps an exact amount of ETH for as many output tokens as possible, along the route determined by the path. The first element of path must be WETH, the last is the output token, and any intermediate elements represent intermediate pairs to trade through (if, for example, a direct pair does not exist).\n @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n @param path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.\n @param to Recipient of the output tokens.\n @param deadline Unix timestamp after which the transaction will revert.\n @return amounts The input token amount and all subsequent output token amounts.\n */\n function swapExactETHForTokens(\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable returns (uint256[] memory amounts);\n\n function swapTokensForExactTokens(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapTokensForExactETH(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapETHForExactTokens(\n uint256 amountOut,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable returns (uint256[] memory amounts);\n}\n" + }, + "contracts/interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @notice It is the interface of functions that we use for the canonical WETH contract.\n *\n * @author develop@teller.finance\n */\ninterface IWETH {\n /**\n * @notice It withdraws ETH from the contract by sending it to the caller and reducing the caller's internal balance of WETH.\n * @param amount The amount of ETH to withdraw.\n */\n function withdraw(uint256 amount) external;\n\n /**\n * @notice It deposits ETH into the contract and increases the caller's internal balance of WETH.\n */\n function deposit() external payable;\n\n /**\n * @notice It gets the ETH deposit balance of an {account}.\n * @param account Address to get balance of.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @notice It transfers the WETH amount specified to the given {account}.\n * @param to Address to transfer to\n * @param value Amount of WETH to transfer\n */\n function transfer(address to, uint256 value) external returns (bool);\n}\n" + }, + "contracts/interfaces/uniswap/IUniswapV3Factory.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.8.0;\n\n/// @title The interface for the Uniswap V3 Factory\n/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees\ninterface IUniswapV3Factory {\n /// @notice Emitted when the owner of the factory is changed\n /// @param oldOwner The owner before the owner was changed\n /// @param newOwner The owner after the owner was changed\n event OwnerChanged(address indexed oldOwner, address indexed newOwner);\n\n /// @notice Emitted when a pool is created\n /// @param token0 The first token of the pool by address sort order\n /// @param token1 The second token of the pool by address sort order\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks\n /// @param pool The address of the created pool\n event PoolCreated(\n address indexed token0,\n address indexed token1,\n uint24 indexed fee,\n int24 tickSpacing,\n address pool\n );\n\n /// @notice Emitted when a new fee amount is enabled for pool creation via the factory\n /// @param fee The enabled fee, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee\n event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);\n\n /// @notice Returns the current owner of the factory\n /// @dev Can be changed by the current owner via setOwner\n /// @return The address of the factory owner\n function owner() external view returns (address);\n\n /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled\n /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context\n /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee\n /// @return The tick spacing\n function feeAmountTickSpacing(uint24 fee) external view returns (int24);\n\n /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist\n /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order\n /// @param tokenA The contract address of either token0 or token1\n /// @param tokenB The contract address of the other token\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// @return pool The pool address\n function getPool(address tokenA, address tokenB, uint24 fee)\n external\n view\n returns (address pool);\n\n /// @notice Creates a pool for the given two tokens and fee\n /// @param tokenA One of the two tokens in the desired pool\n /// @param tokenB The other of the two tokens in the desired pool\n /// @param fee The desired fee for the pool\n /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved\n /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments\n /// are invalid.\n /// @return pool The address of the newly created pool\n function createPool(address tokenA, address tokenB, uint24 fee)\n external\n returns (address pool);\n\n /// @notice Updates the owner of the factory\n /// @dev Must be called by the current owner\n /// @param _owner The new owner of the factory\n function setOwner(address _owner) external;\n\n /// @notice Enables a fee amount with the given tickSpacing\n /// @dev Fee amounts may never be removed once enabled\n /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)\n /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount\n function enableFeeAmount(uint24 fee, int24 tickSpacing) external;\n}\n" + }, + "contracts/interfaces/uniswap/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport \"./pool/IUniswapV3PoolImmutables.sol\";\nimport \"./pool/IUniswapV3PoolState.sol\";\nimport \"./pool/IUniswapV3PoolDerivedState.sol\";\nimport \"./pool/IUniswapV3PoolActions.sol\";\nimport \"./pool/IUniswapV3PoolOwnerActions.sol\";\nimport \"./pool/IUniswapV3PoolEvents.sol\";\n\n/// @title The interface for a Uniswap V3 Pool\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\n/// to the ERC20 specification\n/// @dev The pool interface is broken up into many smaller pieces\ninterface IUniswapV3Pool is\n IUniswapV3PoolImmutables,\n IUniswapV3PoolState,\n IUniswapV3PoolDerivedState,\n IUniswapV3PoolActions,\n IUniswapV3PoolOwnerActions,\n IUniswapV3PoolEvents\n{\n\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissionless pool actions\n/// @notice Contains pool methods that can be called by anyone\ninterface IUniswapV3PoolActions {\n /// @notice Sets the initial price for the pool\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\n function initialize(uint160 sqrtPriceX96) external;\n\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\n /// @param recipient The address for which the liquidity will be created\n /// @param tickLower The lower tick of the position in which to add liquidity\n /// @param tickUpper The upper tick of the position in which to add liquidity\n /// @param amount The amount of liquidity to mint\n /// @param data Any data that should be passed through to the callback\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\n function mint(\n address recipient,\n int24 tickLower,\n int24 tickUpper,\n uint128 amount,\n bytes calldata data\n ) external returns (uint256 amount0, uint256 amount1);\n\n /// @notice Collects tokens owed to a position\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\n /// @param recipient The address which should receive the fees collected\n /// @param tickLower The lower tick of the position for which to collect fees\n /// @param tickUpper The upper tick of the position for which to collect fees\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\n /// @return amount0 The amount of fees collected in token0\n /// @return amount1 The amount of fees collected in token1\n function collect(\n address recipient,\n int24 tickLower,\n int24 tickUpper,\n uint128 amount0Requested,\n uint128 amount1Requested\n ) external returns (uint128 amount0, uint128 amount1);\n\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\n /// @dev Fees must be collected separately via a call to #collect\n /// @param tickLower The lower tick of the position for which to burn liquidity\n /// @param tickUpper The upper tick of the position for which to burn liquidity\n /// @param amount How much liquidity to burn\n /// @return amount0 The amount of token0 sent to the recipient\n /// @return amount1 The amount of token1 sent to the recipient\n function burn(int24 tickLower, int24 tickUpper, uint128 amount)\n external\n returns (uint256 amount0, uint256 amount1);\n\n /// @notice Swap token0 for token1, or token1 for token0\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\n /// @param recipient The address to receive the output of the swap\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\n /// @param data Any data to be passed through to the callback\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\n /// @param recipient The address which will receive the token0 and token1 amounts\n /// @param amount0 The amount of token0 to send\n /// @param amount1 The amount of token1 to send\n /// @param data Any data to be passed through to the callback\n function flash(\n address recipient,\n uint256 amount0,\n uint256 amount1,\n bytes calldata data\n ) external;\n\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\n /// the input observationCardinalityNext.\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\n function increaseObservationCardinalityNext(\n uint16 observationCardinalityNext\n ) external;\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolDerivedState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that is not stored\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\n/// blockchain. The functions here may have variable gas costs.\ninterface IUniswapV3PoolDerivedState {\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\n /// you must call it with secondsAgos = [3600, 0].\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\n /// timestamp\n function observe(uint32[] calldata secondsAgos)\n external\n view\n returns (\n int56[] memory tickCumulatives,\n uint160[] memory secondsPerLiquidityCumulativeX128s\n );\n\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\n /// snapshot is taken and the second snapshot is taken.\n /// @param tickLower The lower tick of the range\n /// @param tickUpper The upper tick of the range\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\n /// @return secondsInside The snapshot of seconds per liquidity for the range\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\n external\n view\n returns (\n int56 tickCumulativeInside,\n uint160 secondsPerLiquidityInsideX128,\n uint32 secondsInside\n );\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolEvents.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Events emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolEvents {\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\n event Initialize(uint160 sqrtPriceX96, int24 tick);\n\n /// @notice Emitted when liquidity is minted for a given position\n /// @param sender The address that minted the liquidity\n /// @param owner The owner of the position and recipient of any minted liquidity\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount The amount of liquidity minted to the position range\n /// @param amount0 How much token0 was required for the minted liquidity\n /// @param amount1 How much token1 was required for the minted liquidity\n event Mint(\n address sender,\n address indexed owner,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount,\n uint256 amount0,\n uint256 amount1\n );\n\n /// @notice Emitted when fees are collected by the owner of a position\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\n /// @param owner The owner of the position for which fees are collected\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount0 The amount of token0 fees collected\n /// @param amount1 The amount of token1 fees collected\n event Collect(\n address indexed owner,\n address recipient,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount0,\n uint128 amount1\n );\n\n /// @notice Emitted when a position's liquidity is removed\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\n /// @param owner The owner of the position for which liquidity is removed\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount The amount of liquidity to remove\n /// @param amount0 The amount of token0 withdrawn\n /// @param amount1 The amount of token1 withdrawn\n event Burn(\n address indexed owner,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount,\n uint256 amount0,\n uint256 amount1\n );\n\n /// @notice Emitted by the pool for any swaps between token0 and token1\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param recipient The address that received the output of the swap\n /// @param amount0 The delta of the token0 balance of the pool\n /// @param amount1 The delta of the token1 balance of the pool\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\n /// @param liquidity The liquidity of the pool after the swap\n /// @param tick The log base 1.0001 of price of the pool after the swap\n event Swap(\n address indexed sender,\n address indexed recipient,\n int256 amount0,\n int256 amount1,\n uint160 sqrtPriceX96,\n uint128 liquidity,\n int24 tick\n );\n\n /// @notice Emitted by the pool for any flashes of token0/token1\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param recipient The address that received the tokens from flash\n /// @param amount0 The amount of token0 that was flashed\n /// @param amount1 The amount of token1 that was flashed\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\n event Flash(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1,\n uint256 paid0,\n uint256 paid1\n );\n\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\n /// just before a mint/swap/burn.\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\n event IncreaseObservationCardinalityNext(\n uint16 observationCardinalityNextOld,\n uint16 observationCardinalityNextNew\n );\n\n /// @notice Emitted when the protocol fee is changed by the pool\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\n /// @param feeProtocol0New The updated value of the token0 protocol fee\n /// @param feeProtocol1New The updated value of the token1 protocol fee\n event SetFeeProtocol(\n uint8 feeProtocol0Old,\n uint8 feeProtocol1Old,\n uint8 feeProtocol0New,\n uint8 feeProtocol1New\n );\n\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\n /// @param sender The address that collects the protocol fees\n /// @param recipient The address that receives the collected protocol fees\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\n event CollectProtocol(\n address indexed sender,\n address indexed recipient,\n uint128 amount0,\n uint128 amount1\n );\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolImmutables.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that never changes\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\ninterface IUniswapV3PoolImmutables {\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\n /// @return The contract address\n function factory() external view returns (address);\n\n /// @notice The first of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token0() external view returns (address);\n\n /// @notice The second of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token1() external view returns (address);\n\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\n /// @return The fee\n function fee() external view returns (uint24);\n\n /// @notice The pool tick spacing\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\n /// This value is an int24 to avoid casting even though it is always positive.\n /// @return The tick spacing\n function tickSpacing() external view returns (int24);\n\n /// @notice The maximum amount of position liquidity that can use any tick in the range\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\n /// @return The max amount of liquidity per tick\n function maxLiquidityPerTick() external view returns (uint128);\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolOwnerActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissioned pool actions\n/// @notice Contains pool methods that may only be called by the factory owner\ninterface IUniswapV3PoolOwnerActions {\n /// @notice Set the denominator of the protocol's % share of the fees\n /// @param feeProtocol0 new protocol fee for token0 of the pool\n /// @param feeProtocol1 new protocol fee for token1 of the pool\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\n\n /// @notice Collect the protocol fee accrued to the pool\n /// @param recipient The address to which collected protocol fees should be sent\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\n /// @return amount0 The protocol fee collected in token0\n /// @return amount1 The protocol fee collected in token1\n function collectProtocol(\n address recipient,\n uint128 amount0Requested,\n uint128 amount1Requested\n ) external returns (uint128 amount0, uint128 amount1);\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that can change\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\n/// per transaction\ninterface IUniswapV3PoolState {\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\n /// when accessed externally.\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\n /// boundary.\n /// observationIndex The index of the last oracle observation that was written,\n /// observationCardinality The current maximum number of observations stored in the pool,\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\n /// feeProtocol The protocol fee for both tokens of the pool.\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\n /// unlocked Whether the pool is currently locked to reentrancy\n function slot0()\n external\n view\n returns (\n uint160 sqrtPriceX96,\n int24 tick,\n uint16 observationIndex,\n uint16 observationCardinality,\n uint16 observationCardinalityNext,\n uint8 feeProtocol,\n bool unlocked\n );\n\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\n /// @dev This value can overflow the uint256\n function feeGrowthGlobal0X128() external view returns (uint256);\n\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\n /// @dev This value can overflow the uint256\n function feeGrowthGlobal1X128() external view returns (uint256);\n\n /// @notice The amounts of token0 and token1 that are owed to the protocol\n /// @dev Protocol fees will never exceed uint128 max in either token\n function protocolFees()\n external\n view\n returns (uint128 token0, uint128 token1);\n\n /// @notice The currently in range liquidity available to the pool\n /// @dev This value has no relationship to the total liquidity across all ticks\n function liquidity() external view returns (uint128);\n\n /// @notice Look up information about a specific tick in the pool\n /// @param tick The tick to look up\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\n /// tick upper,\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\n /// a specific position.\n function ticks(int24 tick)\n external\n view\n returns (\n uint128 liquidityGross,\n int128 liquidityNet,\n uint256 feeGrowthOutside0X128,\n uint256 feeGrowthOutside1X128,\n int56 tickCumulativeOutside,\n uint160 secondsPerLiquidityOutsideX128,\n uint32 secondsOutside,\n bool initialized\n );\n\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\n function tickBitmap(int16 wordPosition) external view returns (uint256);\n\n /// @notice Returns the information about a position by the position's key\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\n /// @return _liquidity The amount of liquidity in the position,\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\n function positions(bytes32 key)\n external\n view\n returns (\n uint128 _liquidity,\n uint256 feeGrowthInside0LastX128,\n uint256 feeGrowthInside1LastX128,\n uint128 tokensOwed0,\n uint128 tokensOwed1\n );\n\n /// @notice Returns data about a specific observation index\n /// @param index The element of the observations array to fetch\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\n /// ago, rather than at a specific index in the array.\n /// @return blockTimestamp The timestamp of the observation,\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\n /// Returns initialized whether the observation has been initialized and the values are safe to use\n function observations(uint256 index)\n external\n view\n returns (\n uint32 blockTimestamp,\n int56 tickCumulative,\n uint160 secondsPerLiquidityCumulativeX128,\n bool initialized\n );\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/CommitmentRolloverLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/ICommitmentRolloverLoan.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\ncontract CommitmentRolloverLoan is ICommitmentRolloverLoan {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ILenderCommitmentForwarder public immutable LENDER_COMMITMENT_FORWARDER;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _tellerV2, address _lenderCommitmentForwarder) {\n TELLER_V2 = ITellerV2(_tellerV2);\n LENDER_COMMITMENT_FORWARDER = ILenderCommitmentForwarder(\n _lenderCommitmentForwarder\n );\n }\n\n /**\n * @notice Allows a borrower to rollover a loan to a new commitment.\n * @param _loanId The ID of the existing loan.\n * @param _rolloverAmount The amount to rollover.\n * @param _commitmentArgs Arguments for the commitment to accept.\n * @return newLoanId_ The ID of the new loan created by accepting the commitment.\n */\n function rolloverLoan(\n uint256 _loanId,\n uint256 _rolloverAmount,\n AcceptCommitmentArgs calldata _commitmentArgs\n ) external returns (uint256 newLoanId_) {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n IERC20Upgradeable lendingToken = IERC20Upgradeable(\n TELLER_V2.getLoanLendingToken(_loanId)\n );\n uint256 balanceBefore = lendingToken.balanceOf(address(this));\n\n if (_rolloverAmount > 0) {\n //accept funds from the borrower to this contract\n lendingToken.transferFrom(borrower, address(this), _rolloverAmount);\n }\n\n // Accept commitment and receive funds to this contract\n newLoanId_ = _acceptCommitment(_commitmentArgs);\n\n // Calculate funds received\n uint256 fundsReceived = lendingToken.balanceOf(address(this)) -\n balanceBefore;\n\n // Approve TellerV2 to spend funds and repay loan\n lendingToken.approve(address(TELLER_V2), fundsReceived);\n TELLER_V2.repayLoanFull(_loanId);\n\n uint256 fundsRemaining = lendingToken.balanceOf(address(this)) -\n balanceBefore;\n\n if (fundsRemaining > 0) {\n lendingToken.transfer(borrower, fundsRemaining);\n }\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n * @return _amount The calculated amount, positive if borrower needs to send funds and negative if they will receive funds.\n */\n function calculateRolloverAmount(\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint256 _timestamp\n ) external view returns (int256 _amount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n _amount +=\n int256(repayAmountOwed.principal) +\n int256(repayAmountOwed.interest);\n\n uint256 _marketId = _getMarketIdForCommitment(\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 amountToBorrower = commitmentPrincipalRequested -\n amountToProtocol -\n amountToMarketplace;\n\n _amount -= int256(amountToBorrower);\n }\n\n /**\n * @notice Internally accepts a commitment via the `LENDER_COMMITMENT_FORWARDER`.\n * @param _commitmentArgs Arguments required to accept a commitment.\n * @return bidId_ The ID of the bid associated with the accepted commitment.\n */\n function _acceptCommitment(AcceptCommitmentArgs calldata _commitmentArgs)\n internal\n returns (uint256 bidId_)\n {\n bytes memory responseData = address(LENDER_COMMITMENT_FORWARDER)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n msg.sender\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return LENDER_COMMITMENT_FORWARDER.getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/ExtensionsContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/IExtensionsContext.sol\";\nimport \"@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\nabstract contract ExtensionsContextUpgradeable is IExtensionsContext {\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private userExtensions;\n\n event ExtensionAdded(address extension, address sender);\n event ExtensionRevoked(address extension, address sender);\n\n function hasExtension(address account, address extension)\n public\n view\n returns (bool)\n {\n return userExtensions[account][extension];\n }\n\n function addExtension(address extension) external {\n require(\n _msgSender() != extension,\n \"ExtensionsContextUpgradeable: cannot approve own extension\"\n );\n\n userExtensions[_msgSender()][extension] = true;\n emit ExtensionAdded(extension, _msgSender());\n }\n\n function revokeExtension(address extension) external {\n userExtensions[_msgSender()][extension] = false;\n emit ExtensionRevoked(extension, _msgSender());\n }\n\n function _msgSender() internal view virtual returns (address sender) {\n address sender;\n\n if (msg.data.length >= 20) {\n assembly {\n sender := shr(96, calldataload(sub(calldatasize(), 20)))\n }\n\n if (hasExtension(sender, msg.sender)) {\n return sender;\n }\n }\n\n return msg.sender;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\n//https://docs.aave.com/developers/v/1.0/tutorials/performing-a-flash-loan/...-in-your-project\n\ncontract FlashRolloverLoan_G1 is IFlashLoanSimpleReceiver, IFlashRolloverLoan {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ILenderCommitmentForwarder public immutable LENDER_COMMITMENT_FORWARDER;\n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _lenderCommitmentForwarder,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n LENDER_COMMITMENT_FORWARDER = ILenderCommitmentForwarder(\n _lenderCommitmentForwarder\n );\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /*\n need to pass loanId and borrower \n */\n\n /**\n * @notice Allows a borrower to rollover a loan to a new commitment.\n * @param _loanId The bid id for the loan to repay\n * @param _flashLoanAmount The amount to flash borrow.\n * @param _acceptCommitmentArgs Arguments for the commitment to accept.\n * @return newLoanId_ The ID of the new loan created by accepting the commitment.\n */\n\n /*\n \nThe flash loan amount can naively be the exact amount needed to repay the old loan \n\nIf the new loan pays out (after fees) MORE than the aave loan amount+ fee) then borrower amount can be zero \n\n 1) I could solve for what the new loans payout (before fees and after fees) would NEED to be to make borrower amount 0...\n\n*/\n\n function rolloverLoanWithFlash(\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external returns (uint256 newLoanId_) {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /*\n Notice: If collateral is being rolled over, it needs to be pre-approved from the borrower to the collateral manager \n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n * @notice Internally accepts a commitment via the `LENDER_COMMITMENT_FORWARDER`.\n * @param _commitmentArgs Arguments required to accept a commitment.\n * @return bidId_ The ID of the bid associated with the accepted commitment.\n */\n function _acceptCommitment(\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n bytes memory responseData = address(LENDER_COMMITMENT_FORWARDER)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\n// Interfaces\nimport \"./FlashRolloverLoan_G1.sol\";\n\ncontract FlashRolloverLoan_G2 is FlashRolloverLoan_G1 {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _lenderCommitmentForwarder,\n address _poolAddressesProvider\n )\n FlashRolloverLoan_G1(\n _tellerV2,\n _lenderCommitmentForwarder,\n _poolAddressesProvider\n )\n {}\n\n /*\n\n This assumes that the flash amount will be the repayLoanFull amount !!\n\n */\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return LENDER_COMMITMENT_FORWARDER.getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\ncontract FlashRolloverLoan_G3 is IFlashLoanSimpleReceiver, IFlashRolloverLoan {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ILenderCommitmentForwarder public immutable LENDER_COMMITMENT_FORWARDER;\n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n * @param _lenderCommitmentForwarder The address of the LenderCommitmentForwarder contract.\n * @param _poolAddressesProvider The address of the PoolAddressesProvider.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _lenderCommitmentForwarder,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n LENDER_COMMITMENT_FORWARDER = ILenderCommitmentForwarder(\n _lenderCommitmentForwarder\n );\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /**\n *\n * @notice Allows the borrower to rollover their existing loan using a flash loan mechanism.\n * The borrower might also provide an additional amount during the rollover.\n *\n * @dev The function first verifies that the caller is the borrower of the loan.\n * It then optionally transfers the additional amount specified by the borrower.\n * A flash loan is then taken from the pool to facilitate the rollover and\n * a callback is executed for further operations.\n *\n * @param _loanId Identifier of the existing loan to be rolled over.\n * @param _flashLoanAmount Amount of flash loan to be borrowed for the rollover.\n * @param _borrowerAmount Additional amount that the borrower may want to add during rollover.\n * @param _acceptCommitmentArgs Commitment arguments that might be necessary for internal operations.\n *\n * @return newLoanId_ Identifier of the new loan post rollover.\n */\n function rolloverLoanWithFlash(\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external returns (uint256 newLoanId_) {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /**\n *\n * @notice Callback function that is triggered by Aave during the flash loan process.\n * This function handles the logic to use the borrowed funds to rollover the loan,\n * make necessary repayments, and manage the loan commitments.\n *\n * @dev The function ensures the initiator is this contract, decodes the data provided by\n * the flash loan call, repays the original loan in full, accepts new loan commitments,\n * approves the repayment for the flash loan and then handles any remaining funds.\n * This function should only be called by the FlashLoanPool as ensured by the `onlyFlashLoanPool` modifier.\n *\n * @param _flashToken The token in which the flash loan is borrowed.\n * @param _flashAmount The amount of tokens borrowed via the flash loan.\n * @param _flashFees The fees associated with the flash loan to be repaid to Aave.\n * @param _initiator The address initiating the flash loan (must be this contract).\n * @param _data Encoded data containing necessary information for loan rollover.\n *\n * @return Returns true if the operation was successful.\n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address _initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n _initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n /**\n *\n *\n * @notice Internal function that repays a loan in full on behalf of this contract.\n *\n * @dev The function first calculates the funds held by the contract before repayment, then approves\n * the repayment amount to the TellerV2 contract and finally repays the loan in full.\n *\n * @param _bidId Identifier of the loan to be repaid.\n * @param _principalToken The token in which the loan was originated.\n * @param _repayAmount The amount to be repaid.\n *\n * @return repayAmount_ The actual amount that was used for repayment.\n */\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n *\n *\n * @notice Accepts a loan commitment using either a Merkle proof or standard method.\n *\n * @dev The function first checks if a Merkle proof is provided, based on which it calls the relevant\n * `acceptCommitment` function in the LenderCommitmentForwarder contract.\n *\n * @param borrower The address of the borrower for whom the commitment is being accepted.\n * @param principalToken The token in which the loan is being accepted.\n * @param _commitmentArgs The arguments necessary for accepting the commitment.\n *\n * @return bidId_ Identifier of the accepted loan.\n * @return acceptCommitmentAmount_ The amount received from accepting the commitment.\n */\n function _acceptCommitment(\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n bool usingMerkleProof = _commitmentArgs.merkleProof.length > 0;\n\n if (usingMerkleProof) {\n bytes memory responseData = address(LENDER_COMMITMENT_FORWARDER)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipientAndProof\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration,\n _commitmentArgs.merkleProof\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n } else {\n bytes memory responseData = address(LENDER_COMMITMENT_FORWARDER)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return LENDER_COMMITMENT_FORWARDER.getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G4.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan_G4.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\ncontract FlashRolloverLoan_G4 is IFlashLoanSimpleReceiver, IFlashRolloverLoan_G4 {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n \n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n * @param _lenderCommitmentForwarder The address of the LenderCommitmentForwarder contract.\n * @param _poolAddressesProvider The address of the PoolAddressesProvider.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /**\n *\n * @notice Allows the borrower to rollover their existing loan using a flash loan mechanism.\n * The borrower might also provide an additional amount during the rollover.\n *\n * @dev The function first verifies that the caller is the borrower of the loan.\n * It then optionally transfers the additional amount specified by the borrower.\n * A flash loan is then taken from the pool to facilitate the rollover and\n * a callback is executed for further operations.\n *\n * @param _loanId Identifier of the existing loan to be rolled over.\n * @param _flashLoanAmount Amount of flash loan to be borrowed for the rollover.\n * @param _borrowerAmount Additional amount that the borrower may want to add during rollover.\n * @param _acceptCommitmentArgs Commitment arguments that might be necessary for internal operations.\n *\n * @return newLoanId_ Identifier of the new loan post rollover.\n */\n function rolloverLoanWithFlash(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external returns (uint256 newLoanId_) {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n lenderCommitmentForwarder :_lenderCommitmentForwarder,\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /**\n *\n * @notice Callback function that is triggered by Aave during the flash loan process.\n * This function handles the logic to use the borrowed funds to rollover the loan,\n * make necessary repayments, and manage the loan commitments.\n *\n * @dev The function ensures the initiator is this contract, decodes the data provided by\n * the flash loan call, repays the original loan in full, accepts new loan commitments,\n * approves the repayment for the flash loan and then handles any remaining funds.\n * This function should only be called by the FlashLoanPool as ensured by the `onlyFlashLoanPool` modifier.\n *\n * @param _flashToken The token in which the flash loan is borrowed.\n * @param _flashAmount The amount of tokens borrowed via the flash loan.\n * @param _flashFees The fees associated with the flash loan to be repaid to Aave.\n * @param _initiator The address initiating the flash loan (must be this contract).\n * @param _data Encoded data containing necessary information for loan rollover.\n *\n * @return Returns true if the operation was successful.\n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address _initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n _initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.lenderCommitmentForwarder,\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n /**\n *\n *\n * @notice Internal function that repays a loan in full on behalf of this contract.\n *\n * @dev The function first calculates the funds held by the contract before repayment, then approves\n * the repayment amount to the TellerV2 contract and finally repays the loan in full.\n *\n * @param _bidId Identifier of the loan to be repaid.\n * @param _principalToken The token in which the loan was originated.\n * @param _repayAmount The amount to be repaid.\n *\n * @return repayAmount_ The actual amount that was used for repayment.\n */\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n *\n *\n * @notice Accepts a loan commitment using either a Merkle proof or standard method.\n *\n * @dev The function first checks if a Merkle proof is provided, based on which it calls the relevant\n * `acceptCommitment` function in the LenderCommitmentForwarder contract.\n *\n * @param borrower The address of the borrower for whom the commitment is being accepted.\n * @param principalToken The token in which the loan is being accepted.\n * @param _commitmentArgs The arguments necessary for accepting the commitment.\n *\n * @return bidId_ Identifier of the accepted loan.\n * @return acceptCommitmentAmount_ The amount received from accepting the commitment.\n */\n function _acceptCommitment(\n address lenderCommitmentForwarder,\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n bool usingMerkleProof = _commitmentArgs.merkleProof.length > 0;\n\n if (usingMerkleProof) {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipientAndProof\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration,\n _commitmentArgs.merkleProof\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n } else {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(_lenderCommitmentForwarder,\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(address _lenderCommitmentForwarder, uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return ILenderCommitmentForwarder(_lenderCommitmentForwarder).getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}\n \n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G5.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/ISmartCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan_G4.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\ncontract FlashRolloverLoan_G5 is IFlashLoanSimpleReceiver, IFlashRolloverLoan_G4 {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n \n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n address smartCommitmentAddress; //if this is not address(0), we will use this ! leave empty if not used. \n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n * @param _lenderCommitmentForwarder The address of the LenderCommitmentForwarder contract.\n * @param _poolAddressesProvider The address of the PoolAddressesProvider.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /**\n *\n * @notice Allows the borrower to rollover their existing loan using a flash loan mechanism.\n * The borrower might also provide an additional amount during the rollover.\n *\n * @dev The function first verifies that the caller is the borrower of the loan.\n * It then optionally transfers the additional amount specified by the borrower.\n * A flash loan is then taken from the pool to facilitate the rollover and\n * a callback is executed for further operations.\n *\n * @param _loanId Identifier of the existing loan to be rolled over.\n * @param _flashLoanAmount Amount of flash loan to be borrowed for the rollover.\n * @param _borrowerAmount Additional amount that the borrower may want to add during rollover.\n * @param _acceptCommitmentArgs Commitment arguments that might be necessary for internal operations.\n * \n */\n function rolloverLoanWithFlash(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n lenderCommitmentForwarder :_lenderCommitmentForwarder,\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /**\n *\n * @notice Callback function that is triggered by Aave during the flash loan process.\n * This function handles the logic to use the borrowed funds to rollover the loan,\n * make necessary repayments, and manage the loan commitments.\n *\n * @dev The function ensures the initiator is this contract, decodes the data provided by\n * the flash loan call, repays the original loan in full, accepts new loan commitments,\n * approves the repayment for the flash loan and then handles any remaining funds.\n * This function should only be called by the FlashLoanPool as ensured by the `onlyFlashLoanPool` modifier.\n *\n * @param _flashToken The token in which the flash loan is borrowed.\n * @param _flashAmount The amount of tokens borrowed via the flash loan.\n * @param _flashFees The fees associated with the flash loan to be repaid to Aave.\n * @param _initiator The address initiating the flash loan (must be this contract).\n * @param _data Encoded data containing necessary information for loan rollover.\n *\n * @return Returns true if the operation was successful.\n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address _initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n _initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.lenderCommitmentForwarder,\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n /**\n *\n *\n * @notice Internal function that repays a loan in full on behalf of this contract.\n *\n * @dev The function first calculates the funds held by the contract before repayment, then approves\n * the repayment amount to the TellerV2 contract and finally repays the loan in full.\n *\n * @param _bidId Identifier of the loan to be repaid.\n * @param _principalToken The token in which the loan was originated.\n * @param _repayAmount The amount to be repaid.\n *\n * @return repayAmount_ The actual amount that was used for repayment.\n */\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n *\n *\n * @notice Accepts a loan commitment using either a Merkle proof or standard method.\n *\n * @dev The function first checks if a Merkle proof is provided, based on which it calls the relevant\n * `acceptCommitment` function in the LenderCommitmentForwarder contract.\n *\n * @param borrower The address of the borrower for whom the commitment is being accepted.\n * @param principalToken The token in which the loan is being accepted.\n * @param _commitmentArgs The arguments necessary for accepting the commitment.\n *\n * @return bidId_ Identifier of the accepted loan.\n * @return acceptCommitmentAmount_ The amount received from accepting the commitment.\n */\n function _acceptCommitment(\n address lenderCommitmentForwarder,\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n\n\n if (_commitmentArgs.smartCommitmentAddress != address(0)) {\n\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ISmartCommitmentForwarder\n .acceptSmartCommitmentWithRecipient\n .selector,\n _commitmentArgs.smartCommitmentAddress,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n\n }else { \n\n bool usingMerkleProof = _commitmentArgs.merkleProof.length > 0;\n\n if (usingMerkleProof) {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipientAndProof\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration,\n _commitmentArgs.merkleProof\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n } else {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n }\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(_lenderCommitmentForwarder,\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(address _lenderCommitmentForwarder, uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return ILenderCommitmentForwarder(_lenderCommitmentForwarder).getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G6.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/ISmartCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan_G6.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\n\n\n/*\n G6: Additionally incorporates referral rewards \n*/\n\n\ncontract FlashRolloverLoan_G6 is IFlashLoanSimpleReceiver, IFlashRolloverLoan_G6 {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n \n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n address smartCommitmentAddress; //if this is not address(0), we will use this ! leave empty if not used. \n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n * @param _lenderCommitmentForwarder The address of the LenderCommitmentForwarder contract.\n * @param _poolAddressesProvider The address of the PoolAddressesProvider.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /**\n *\n * @notice Allows the borrower to rollover their existing loan using a flash loan mechanism.\n * The borrower might also provide an additional amount during the rollover.\n *\n * @dev The function first verifies that the caller is the borrower of the loan.\n * It then optionally transfers the additional amount specified by the borrower.\n * A flash loan is then taken from the pool to facilitate the rollover and\n * a callback is executed for further operations.\n *\n * @param _loanId Identifier of the existing loan to be rolled over.\n * @param _flashLoanAmount Amount of flash loan to be borrowed for the rollover.\n * @param _borrowerAmount Additional amount that the borrower may want to add during rollover.\n * @param _acceptCommitmentArgs Commitment arguments that might be necessary for internal operations.\n * \n */\n function rolloverLoanWithFlash(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n uint256 _rewardAmount,\n address _rewardRecipient,\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n require( _rewardAmount <= _flashLoanAmount/ 10, \"Reward amount may only be up to 1/10 of flash loan amount\" );\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n lenderCommitmentForwarder :_lenderCommitmentForwarder,\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n rewardRecipient: _rewardRecipient,\n rewardAmount: _rewardAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /**\n *\n * @notice Callback function that is triggered by Aave during the flash loan process.\n * This function handles the logic to use the borrowed funds to rollover the loan,\n * make necessary repayments, and manage the loan commitments.\n *\n * @dev The function ensures the initiator is this contract, decodes the data provided by\n * the flash loan call, repays the original loan in full, accepts new loan commitments,\n * approves the repayment for the flash loan and then handles any remaining funds.\n * This function should only be called by the FlashLoanPool as ensured by the `onlyFlashLoanPool` modifier.\n *\n * @param _flashToken The token in which the flash loan is borrowed.\n * @param _flashAmount The amount of tokens borrowed via the flash loan.\n * @param _flashFees The fees associated with the flash loan to be repaid to Aave.\n * @param _initiator The address initiating the flash loan (must be this contract).\n * @param _data Encoded data containing necessary information for loan rollover.\n *\n * @return Returns true if the operation was successful.\n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address _initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n _initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.lenderCommitmentForwarder,\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n\n if (_rolloverArgs.rewardAmount > 0){\n\n //make sure reward amount isnt TOO much here ? \n\n fundsRemaining -= _rolloverArgs.rewardAmount;\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.rewardRecipient,\n _rolloverArgs.rewardAmount\n );\n\n }\n\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n /**\n *\n *\n * @notice Internal function that repays a loan in full on behalf of this contract.\n *\n * @dev The function first calculates the funds held by the contract before repayment, then approves\n * the repayment amount to the TellerV2 contract and finally repays the loan in full.\n *\n * @param _bidId Identifier of the loan to be repaid.\n * @param _principalToken The token in which the loan was originated.\n * @param _repayAmount The amount to be repaid.\n *\n * @return repayAmount_ The actual amount that was used for repayment.\n */\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n *\n *\n * @notice Accepts a loan commitment using either a Merkle proof or standard method.\n *\n * @dev The function first checks if a Merkle proof is provided, based on which it calls the relevant\n * `acceptCommitment` function in the LenderCommitmentForwarder contract.\n *\n * @param borrower The address of the borrower for whom the commitment is being accepted.\n * @param principalToken The token in which the loan is being accepted.\n * @param _commitmentArgs The arguments necessary for accepting the commitment.\n *\n * @return bidId_ Identifier of the accepted loan.\n * @return acceptCommitmentAmount_ The amount received from accepting the commitment.\n */\n function _acceptCommitment(\n address lenderCommitmentForwarder,\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n\n\n if (_commitmentArgs.smartCommitmentAddress != address(0)) {\n\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ISmartCommitmentForwarder\n .acceptSmartCommitmentWithRecipient\n .selector,\n _commitmentArgs.smartCommitmentAddress,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n\n }else { \n\n bool usingMerkleProof = _commitmentArgs.merkleProof.length > 0;\n\n if (usingMerkleProof) {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipientAndProof\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration,\n _commitmentArgs.merkleProof\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n } else {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n }\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint256 _rewardAmount, \n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(_lenderCommitmentForwarder,\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee) -\n int256(_rewardAmount);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(address _lenderCommitmentForwarder, uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return ILenderCommitmentForwarder(_lenderCommitmentForwarder).getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n \nimport \"./FlashRolloverLoan_G5.sol\";\n\ncontract FlashRolloverLoan is FlashRolloverLoan_G5 {\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n )\n FlashRolloverLoan_G5(\n _tellerV2,\n _poolAddressesProvider\n )\n {}\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoanWidget.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n \nimport \"./FlashRolloverLoan_G6.sol\";\n\ncontract FlashRolloverLoanWidget is FlashRolloverLoan_G6 {\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n )\n FlashRolloverLoan_G6(\n _tellerV2,\n _poolAddressesProvider\n )\n {}\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\"; \n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../../interfaces/ITellerV2.sol\";\nimport \"../../../interfaces/IProtocolFee.sol\";\nimport \"../../../interfaces/ITellerV2Storage.sol\";\nimport \"../../../libraries/NumbersLib.sol\";\n\nimport {IUniswapPricingLibrary} from \"../../../interfaces/IUniswapPricingLibrary.sol\";\n\nimport \"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\";\n \nimport { ILenderCommitmentGroup } from \"../../../interfaces/ILenderCommitmentGroup.sol\";\n\ncontract LenderCommitmentGroupFactory is OwnableUpgradeable {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n \n //this is the beacon proxy\n address public lenderGroupBeacon;\n\n\n mapping(address => uint256) public deployedLenderGroupContracts;\n\n event DeployedLenderGroupContract(address indexed groupContract);\n\n \n\n function initialize(address _lenderGroupBeacon )\n external\n initializer\n {\n lenderGroupBeacon = _lenderGroupBeacon; \n __Ownable_init_unchained();\n }\n\n\n /*\n This should deploy a new lender commitment group pool contract.\n It will use create commitment args in order to define the pool contracts parameters such as its primary principal token. \n Shares will be distributed at a 1:1 ratio of the primary principal token so if 1e18 raw WETH are deposited, the depositor gets 1e18 shares for the group pool.\n */\n function deployLenderCommitmentGroupPool(\n uint256 _initialPrincipalAmount,\n ILenderCommitmentGroup.CommitmentGroupConfig calldata _commitmentGroupConfig,\n IUniswapPricingLibrary.PoolRouteConfig[] calldata _poolOracleRoutes\n ) external returns (address newGroupContract_) {\n \n\n \n BeaconProxy newGroupContract_ = new BeaconProxy(\n lenderGroupBeacon,\n abi.encodeWithSelector(\n ILenderCommitmentGroup.initialize.selector, //this initializes \n _commitmentGroupConfig,\n _poolOracleRoutes\n\n )\n );\n\n deployedLenderGroupContracts[address(newGroupContract_)] = block.number; //consider changing this ?\n emit DeployedLenderGroupContract(address(newGroupContract_));\n\n\n\n //it is not absolutely necessary to have this call here but it allows the user to potentially save a tx step so it is nice to have .\n if (_initialPrincipalAmount > 0) {\n //should pull in the creators initial committed principal tokens .\n\n //send the initial principal tokens to _newgroupcontract here !\n // so it will have them for addPrincipalToCommitmentGroup which will pull them from here\n\n _addPrincipalToCommitmentGroup(\n address(newGroupContract_),\n _initialPrincipalAmount,\n _commitmentGroupConfig.principalTokenAddress \n \n );\n\n \n } \n\n\n //transfer ownership to msg.sender \n OwnableUpgradeable(address(newGroupContract_))\n .transferOwnership(msg.sender);\n }\n\n\n\n function _addPrincipalToCommitmentGroup(\n address _newGroupContract,\n uint256 _initialPrincipalAmount,\n address _principalTokenAddress\n ) internal {\n\n\n IERC20(_principalTokenAddress).transferFrom(\n msg.sender,\n address(this),\n _initialPrincipalAmount\n );\n IERC20(_principalTokenAddress).approve(\n _newGroupContract,\n _initialPrincipalAmount\n );\n\n address sharesRecipient = msg.sender; \n\n uint256 sharesAmount_ = ILenderCommitmentGroup(address(_newGroupContract))\n .addPrincipalToCommitmentGroup(\n _initialPrincipalAmount,\n sharesRecipient,\n 0 //_minShares\n );\n\n\n }\n\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n\n// Interfaces\nimport \"../../../interfaces/ITellerV2Context.sol\";\nimport \"../../../interfaces/IProtocolFee.sol\";\n \nimport \"../../../interfaces/ITellerV2.sol\";\n\n//import \"../../../interfaces/IFlashRolloverLoan.sol\";\nimport \"../../../libraries/NumbersLib.sol\";\n\nimport \"../../../interfaces/uniswap/IUniswapV3Pool.sol\";\n\nimport \"../../../interfaces/uniswap/IUniswapV3Factory.sol\";\nimport \"../../../interfaces/ISmartCommitmentForwarder.sol\";\n\nimport \"../../../libraries/uniswap/TickMath.sol\";\nimport \"../../../libraries/uniswap/FixedPoint96.sol\";\nimport \"../../../libraries/uniswap/FullMath.sol\";\n\nimport {LenderCommitmentGroupShares} from \"./LenderCommitmentGroupShares.sol\";\n\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\nimport { CommitmentCollateralType, ISmartCommitment } from \"../../../interfaces/ISmartCommitment.sol\";\nimport { ILoanRepaymentListener } from \"../../../interfaces/ILoanRepaymentListener.sol\";\n\nimport { ILoanRepaymentCallbacks } from \"../../../interfaces/ILoanRepaymentCallbacks.sol\";\n\nimport { IEscrowVault } from \"../../../interfaces/IEscrowVault.sol\";\n\nimport { IPausableTimestamp } from \"../../../interfaces/IPausableTimestamp.sol\";\nimport { ILenderCommitmentGroup } from \"../../../interfaces/ILenderCommitmentGroup.sol\";\nimport { Payment } from \"../../../TellerV2Storage.sol\";\n\nimport {IUniswapPricingLibrary} from \"../../../interfaces/IUniswapPricingLibrary.sol\";\nimport {UniswapPricingLibrary} from \"../../../libraries/UniswapPricingLibrary.sol\";\n\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n/*\n \n\n Each LenderCommitmentGroup SmartContract acts as its own Loan Commitment (for the SmartCommitmentForwarder) and acts as its own Lender in the Teller Protocol.\n\n Lender Users can deposit principal tokens in this contract and this will give them Share Tokens (LP tokens) representing their ownership in the liquidity pool of this contract.\n\n Borrower Users can borrow principal token funds from this contract (via the SCF contract) by providing collateral tokens in the proper amount as specified by the rules of this smart contract.\n These collateral tokens are then owned by this smart contract and are returned to the borrower via the Teller Protocol rules to the borrower if and only if the borrower repays principal and interest of the loan they took.\n\n If the borrower defaults on a loan, for 24 hours a liquidation auction is automatically conducted by this smart contract in order to incentivize a liquidator to take the collateral tokens in exchange for principal tokens.\n\n \n \n\n*/\n\ncontract LenderCommitmentGroup_Smart is\n ILenderCommitmentGroup,\n ISmartCommitment,\n ILoanRepaymentListener,\n IPausableTimestamp,\n Initializable,\n OwnableUpgradeable,\n PausableUpgradeable\n{\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n uint256 public immutable STANDARD_EXPANSION_FACTOR = 1e18;\n\n uint256 public immutable MIN_TWAP_INTERVAL = 3;\n\n uint256 public immutable UNISWAP_EXPANSION_FACTOR = 2**96;\n\n uint256 public immutable EXCHANGE_RATE_EXPANSION_FACTOR = 1e36; \n\n using SafeERC20 for IERC20;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable TELLER_V2;\n address public immutable SMART_COMMITMENT_FORWARDER;\n address public immutable UNISWAP_V3_FACTORY;\n address private UNISWAP_V3_POOL; //deprecated\n \n LenderCommitmentGroupShares public poolSharesToken;\n\n IERC20 public principalToken;\n IERC20 public collateralToken;\n uint24 private _uniswapPoolFee; //deprecated\n\n uint256 marketId;\n\n \n uint256 public totalPrincipalTokensCommitted; \n uint256 public totalPrincipalTokensWithdrawn;\n\n uint256 public totalPrincipalTokensLended;\n uint256 public totalPrincipalTokensRepaid; //subtract this and the above to find total principal tokens outstanding for loans\n\n \n \n uint256 public totalInterestCollected;\n\n uint16 public liquidityThresholdPercent; //5000 is 50 pct // enforce max of 10000\n uint16 public collateralRatio; //the overcollateralization ratio, typically 80 pct\n\n uint32 private _twapInterval; //deprecated\n uint32 public maxLoanDuration;\n uint16 public interestRateLowerBound;\n uint16 public interestRateUpperBound;\n\n\n\n\n mapping(address => uint256) public poolSharesPreparedToWithdrawForLender;\n mapping(address => uint256) public poolSharesPreparedTimestamp;\n uint256 immutable public DEFAULT_WITHDRAWL_DELAY_TIME_SECONDS = 300;\n uint256 immutable public MAX_WITHDRAWL_DELAY_TIME = 86400;\n\n //mapping(address => uint256) public principalTokensCommittedByLender;\n mapping(uint256 => bool) public activeBids;\n\n //this excludes interest\n // maybe it is possible to get rid of this storage slot and calculate it from totalPrincipalTokensRepaid, totalPrincipalTokensLended\n int256 tokenDifferenceFromLiquidations;\n\n bool public firstDepositMade;\n uint256 public withdrawlDelayTimeSeconds; \n\n IUniswapPricingLibrary.PoolRouteConfig[] public poolOracleRoutes ;\n\n //configured by the owner. If 0 , not used. \n uint256 public maxPrincipalPerCollateralAmount; \n\n\n uint256 public lastUnpausedAt;\n \n\n event PoolInitialized(\n address indexed principalTokenAddress,\n address indexed collateralTokenAddress,\n uint256 marketId,\n uint32 maxLoanDuration,\n uint16 interestRateLowerBound,\n uint16 interestRateUpperBound,\n uint16 liquidityThresholdPercent,\n uint16 loanToValuePercent,\n // uint24 uniswapPoolFee,\n // uint32 twapInterval,\n address poolSharesToken\n );\n\n event LenderAddedPrincipal(\n address indexed lender,\n uint256 amount,\n uint256 sharesAmount,\n address indexed sharesRecipient\n );\n\n event BorrowerAcceptedFunds(\n address indexed borrower,\n uint256 indexed bidId,\n uint256 principalAmount,\n uint256 collateralAmount,\n uint32 loanDuration,\n uint16 interestRate\n );\n\n event EarningsWithdrawn(\n address indexed lender,\n uint256 amountPoolSharesTokens,\n uint256 principalTokensWithdrawn,\n address indexed recipient\n );\n\n\n event DefaultedLoanLiquidated(\n uint256 indexed bidId,\n address indexed liquidator,\n uint256 amountDue, \n int256 tokenAmountDifference \n );\n\n\n event LoanRepaid(\n uint256 indexed bidId,\n address indexed repayer,\n uint256 principalAmount,\n uint256 interestAmount,\n uint256 totalPrincipalRepaid,\n uint256 totalInterestCollected\n );\n\n event PoolSharesPrepared(\n address lender,\n uint256 sharesAmount,\n uint256 preparedAt\n\n );\n\n\n modifier onlySmartCommitmentForwarder() {\n require(\n msg.sender == address(SMART_COMMITMENT_FORWARDER),\n \"Can only be called by Smart Commitment Forwarder\"\n );\n _;\n }\n\n modifier onlyTellerV2() {\n require(\n msg.sender == address(TELLER_V2),\n \"Can only be called by TellerV2\"\n );\n _;\n }\n\n\n modifier onlyProtocolOwner() {\n require(\n msg.sender == Ownable(address(TELLER_V2)).owner(),\n \"Can only be called by TellerV2\"\n );\n _;\n }\n\n modifier bidIsActiveForGroup(uint256 _bidId) {\n require(activeBids[_bidId] == true, \"Bid is not active for group\");\n\n _;\n }\n\n modifier whenForwarderNotPaused() {\n require( PausableUpgradeable(address(SMART_COMMITMENT_FORWARDER)).paused() == false , \"Smart Commitment Forwarder is paused\");\n _;\n }\n\n\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _smartCommitmentForwarder,\n address _uniswapV3Factory\n ) {\n TELLER_V2 = _tellerV2;\n SMART_COMMITMENT_FORWARDER = _smartCommitmentForwarder;\n UNISWAP_V3_FACTORY = _uniswapV3Factory;\n \n }\n\n /*\n\n\n \n */\n function initialize(\n CommitmentGroupConfig calldata _commitmentGroupConfig,\n IUniswapPricingLibrary.PoolRouteConfig[] calldata _poolOracleRoutes\n ) external initializer returns (address poolSharesToken_) {\n \n __Ownable_init();\n __Pausable_init();\n\n principalToken = IERC20(_commitmentGroupConfig.principalTokenAddress);\n collateralToken = IERC20(_commitmentGroupConfig.collateralTokenAddress);\n /*uniswapPoolFee = _commitmentGroupConfig.uniswapPoolFee;\n\n UNISWAP_V3_POOL = IUniswapV3Factory(UNISWAP_V3_FACTORY).getPool(\n _commitmentGroupConfig.principalTokenAddress,\n _commitmentGroupConfig.collateralTokenAddress,\n _commitmentGroupConfig.uniswapPoolFee\n );*/\n\n //require(_commitmentGroupConfig.twapInterval >= MIN_TWAP_INTERVAL, \"Invalid TWAP Interval\");\n // require(UNISWAP_V3_POOL != address(0), \"Invalid uniswap pool address\");\n\n marketId = _commitmentGroupConfig.marketId;\n\n withdrawlDelayTimeSeconds = DEFAULT_WITHDRAWL_DELAY_TIME_SECONDS;\n\n //in order for this to succeed, first, that SmartCommitmentForwarder needs to be THE trusted forwarder for the market\n\n \n ITellerV2Context(TELLER_V2).approveMarketForwarder(\n _commitmentGroupConfig.marketId,\n SMART_COMMITMENT_FORWARDER\n );\n\n maxLoanDuration = _commitmentGroupConfig.maxLoanDuration;\n interestRateLowerBound = _commitmentGroupConfig.interestRateLowerBound;\n interestRateUpperBound = _commitmentGroupConfig.interestRateUpperBound;\n\n\n \n \n require(interestRateLowerBound <= interestRateUpperBound, \"invalid _interestRateLowerBound\");\n\n \n liquidityThresholdPercent = _commitmentGroupConfig.liquidityThresholdPercent;\n collateralRatio = _commitmentGroupConfig.collateralRatio;\n //twapInterval = _commitmentGroupConfig.twapInterval;\n\n require( liquidityThresholdPercent <= 10000, \"invalid _liquidityThresholdPercent\"); \n\n \n\n for (uint256 i = 0; i < _poolOracleRoutes.length; i++) {\n poolOracleRoutes.push(_poolOracleRoutes[i]);\n }\n\n\n require(poolOracleRoutes.length >= 1 && poolOracleRoutes.length <= 2, \"invalid pool routes length\");\n \n poolSharesToken_ = _deployPoolSharesToken();\n\n\n emit PoolInitialized(\n _commitmentGroupConfig.principalTokenAddress,\n _commitmentGroupConfig.collateralTokenAddress,\n _commitmentGroupConfig.marketId,\n _commitmentGroupConfig.maxLoanDuration,\n _commitmentGroupConfig.interestRateLowerBound,\n _commitmentGroupConfig.interestRateUpperBound,\n _commitmentGroupConfig.liquidityThresholdPercent,\n _commitmentGroupConfig.collateralRatio,\n //_commitmentGroupConfig.uniswapPoolFee,\n //_commitmentGroupConfig.twapInterval,\n poolSharesToken_\n );\n }\n\n\n\n function setWithdrawlDelayTime(uint256 _seconds) \n external \n onlyProtocolOwner {\n\n require( _seconds < MAX_WITHDRAWL_DELAY_TIME );\n\n withdrawlDelayTimeSeconds = _seconds;\n }\n\n\n\n function setMaxPrincipalPerCollateralAmount(uint256 _maxPrincipalPerCollateralAmount) \n external \n onlyOwner {\n\n maxPrincipalPerCollateralAmount = _maxPrincipalPerCollateralAmount;\n }\n\n function _deployPoolSharesToken()\n internal\n onlyInitializing\n returns (address poolSharesToken_)\n {\n \n require(\n address(poolSharesToken) == address(0),\n \"Pool shares already deployed\"\n );\n \n poolSharesToken = new LenderCommitmentGroupShares(\n \"LenderGroupShares\",\n \"SHR\",\n 18 \n );\n\n return address(poolSharesToken);\n } \n\n\n /**\n * @notice This determines the number of shares you get for depositing principal tokens and the number of principal tokens you receive for burning shares\n * @return rate_ The current exchange rate, scaled by the EXCHANGE_RATE_FACTOR.\n */\n\n function sharesExchangeRate() public view virtual returns (uint256 rate_) {\n \n\n uint256 poolTotalEstimatedValue = getPoolTotalEstimatedValue();\n\n if (poolSharesToken.totalSupply() == 0) {\n return EXCHANGE_RATE_EXPANSION_FACTOR; // 1 to 1 for first swap\n }\n\n rate_ =\n MathUpgradeable.mulDiv(poolTotalEstimatedValue , \n EXCHANGE_RATE_EXPANSION_FACTOR ,\n poolSharesToken.totalSupply() );\n }\n\n function sharesExchangeRateInverse()\n public\n view\n virtual\n returns (uint256 rate_)\n {\n return\n (EXCHANGE_RATE_EXPANSION_FACTOR * EXCHANGE_RATE_EXPANSION_FACTOR) /\n sharesExchangeRate();\n }\n\n function getPoolTotalEstimatedValue()\n public\n view\n returns (uint256 poolTotalEstimatedValue_)\n {\n \n int256 poolTotalEstimatedValueSigned = int256(totalPrincipalTokensCommitted) \n + int256(totalInterestCollected) + int256(tokenDifferenceFromLiquidations) \n - int256(totalPrincipalTokensWithdrawn);\n\n //if the poolTotalEstimatedValue_ is less than 0, we treat it as 0. \n poolTotalEstimatedValue_ = poolTotalEstimatedValueSigned > int256(0)\n ? uint256(poolTotalEstimatedValueSigned)\n : 0;\n }\n\n /*\n must be initialized for this to work ! \n */\n function addPrincipalToCommitmentGroup(\n uint256 _amount,\n address _sharesRecipient,\n uint256 _minSharesAmountOut\n ) external whenForwarderNotPaused whenNotPaused returns (uint256 sharesAmount_) {\n //transfers the primary principal token from msg.sender into this contract escrow\n\n \n\n \n \n uint256 principalTokenBalanceBefore = principalToken.balanceOf(address(this));\n\n principalToken.safeTransferFrom(msg.sender, address(this), _amount);\n \n uint256 principalTokenBalanceAfter = principalToken.balanceOf(address(this));\n \n require( principalTokenBalanceAfter == principalTokenBalanceBefore + _amount, \"Token balance was not added properly\" );\n\n\n\n sharesAmount_ = _valueOfUnderlying(_amount, sharesExchangeRate());\n\n \n\n totalPrincipalTokensCommitted += _amount;\n \n\n //mint shares equal to _amount and give them to the shares recipient !!!\n poolSharesToken.mint(_sharesRecipient, sharesAmount_);\n \n \n\n // prepare current balance \n uint256 sharesBalance = poolSharesToken.balanceOf(address(_sharesRecipient));\n _prepareSharesForWithdraw(_sharesRecipient,sharesBalance); \n\n\n emit LenderAddedPrincipal( \n\n msg.sender,\n _amount,\n sharesAmount_,\n _sharesRecipient\n\n );\n\n require( sharesAmount_ >= _minSharesAmountOut, \"Invalid: Min Shares AmountOut\" );\n \n if(!firstDepositMade){\n require(msg.sender == owner(), \"Owner must initialize the pool with a deposit first.\");\n require( sharesAmount_>= 1e6, \"Initial shares amount must be atleast 1e6\" );\n\n firstDepositMade = true;\n }\n }\n\n function _valueOfUnderlying(uint256 amount, uint256 rate)\n internal\n pure\n returns (uint256 value_)\n {\n if (rate == 0) {\n return 0;\n }\n\n value_ = MathUpgradeable.mulDiv(amount , EXCHANGE_RATE_EXPANSION_FACTOR , rate ) ;\n }\n\n function acceptFundsForAcceptBid(\n address _borrower,\n uint256 _bidId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n address _collateralTokenAddress,\n uint256 _collateralTokenId, \n uint32 _loanDuration,\n uint16 _interestRate\n ) external onlySmartCommitmentForwarder whenForwarderNotPaused whenNotPaused {\n \n require(\n _collateralTokenAddress == address(collateralToken),\n \"Mismatching collateral token\"\n );\n //the interest rate must be at least as high has the commitment demands. The borrower can use a higher interest rate although that would not be beneficial to the borrower.\n require(_interestRate >= getMinInterestRate(_principalAmount), \"Invalid interest rate\");\n //the loan duration must be less than the commitment max loan duration. The lender who made the commitment expects the money to be returned before this window.\n require(_loanDuration <= maxLoanDuration, \"Invalid loan max duration\");\n\n require(\n getPrincipalAmountAvailableToBorrow() >= _principalAmount,\n \"Invalid loan max principal\"\n );\n \n \n uint256 requiredCollateral = calculateCollateralRequiredToBorrowPrincipal(\n _principalAmount\n );\n\n\n\n require( \n _collateralAmount >=\n requiredCollateral,\n \"Insufficient Borrower Collateral\"\n );\n \n principalToken.approve(address(TELLER_V2), _principalAmount);\n\n //do not have to spoof/forward as this contract is the lender !\n _acceptBidWithRepaymentListener(_bidId);\n\n totalPrincipalTokensLended += _principalAmount;\n\n activeBids[_bidId] = true; //bool for now\n \n\n emit BorrowerAcceptedFunds( \n _borrower,\n _bidId,\n _principalAmount,\n _collateralAmount, \n _loanDuration,\n _interestRate \n );\n }\n\n function _acceptBidWithRepaymentListener(uint256 _bidId) internal {\n ITellerV2(TELLER_V2).lenderAcceptBid(_bidId); //this gives out the funds to the borrower\n\n ILoanRepaymentCallbacks(TELLER_V2).setRepaymentListenerForBid(\n _bidId,\n address(this)\n );\n\n \n }\n\n function prepareSharesForWithdraw(\n uint256 _amountPoolSharesTokens \n ) external whenForwarderNotPaused whenNotPaused returns (bool) {\n \n return _prepareSharesForWithdraw(msg.sender, _amountPoolSharesTokens); \n }\n\n function _prepareSharesForWithdraw(\n address _recipient,\n uint256 _amountPoolSharesTokens \n ) internal returns (bool) {\n \n require( poolSharesToken.balanceOf(_recipient) >= _amountPoolSharesTokens );\n\n poolSharesPreparedToWithdrawForLender[_recipient] = _amountPoolSharesTokens; \n poolSharesPreparedTimestamp[_recipient] = block.timestamp; \n\n\n emit PoolSharesPrepared( \n\n _recipient,\n _amountPoolSharesTokens,\n block.timestamp\n\n );\n\n return true; \n }\n\n\n /*\n \n */\n function burnSharesToWithdrawEarnings(\n uint256 _amountPoolSharesTokens,\n address _recipient,\n uint256 _minAmountOut\n ) external whenForwarderNotPaused whenNotPaused returns (uint256) {\n \n require(poolSharesPreparedToWithdrawForLender[msg.sender] >= _amountPoolSharesTokens,\"Shares not prepared for withdraw\");\n require(poolSharesPreparedTimestamp[msg.sender] <= block.timestamp - withdrawlDelayTimeSeconds,\"Shares not prepared for withdraw\");\n \n \n poolSharesPreparedToWithdrawForLender[msg.sender] = 0;\n poolSharesPreparedTimestamp[msg.sender] = block.timestamp;\n \n \n //this should compute BEFORE shares burn \n uint256 principalTokenValueToWithdraw = _valueOfUnderlying(\n _amountPoolSharesTokens,\n sharesExchangeRateInverse()\n );\n\n poolSharesToken.burn(msg.sender, _amountPoolSharesTokens);\n\n totalPrincipalTokensWithdrawn += principalTokenValueToWithdraw;\n\n principalToken.safeTransfer(_recipient, principalTokenValueToWithdraw);\n\n\n emit EarningsWithdrawn(\n msg.sender,\n _amountPoolSharesTokens,\n principalTokenValueToWithdraw,\n _recipient\n );\n \n require( principalTokenValueToWithdraw >= _minAmountOut ,\"Invalid: Min Amount Out\");\n\n return principalTokenValueToWithdraw;\n }\n\n /*\n\n\n */\n\n function liquidateDefaultedLoanWithIncentive(\n uint256 _bidId,\n int256 _tokenAmountDifference\n ) public whenForwarderNotPaused whenNotPaused bidIsActiveForGroup(_bidId) {\n \n //use original principal amount as amountDue\n\n uint256 amountDue = _getAmountOwedForBid(_bidId);\n\n \n\n uint256 loanDefaultedTimeStamp = ITellerV2(TELLER_V2)\n .getLoanDefaultTimestamp(_bidId);\n\n uint256 loanDefaultedOrUnpausedAtTimeStamp = Math.max(\n loanDefaultedTimeStamp,\n getLastUnpausedAt()\n );\n\n int256 minAmountDifference = getMinimumAmountDifferenceToCloseDefaultedLoan(\n amountDue,\n loanDefaultedOrUnpausedAtTimeStamp\n );\n\n require(\n _tokenAmountDifference >= minAmountDifference,\n \"Insufficient tokenAmountDifference\"\n );\n\n\n if (minAmountDifference > 0) {\n //this is used when the collateral value is higher than the principal (rare)\n //the loan will be completely made whole and our contract gets extra funds too\n uint256 tokensToTakeFromSender = abs(minAmountDifference);\n\n \n \n \n uint256 liquidationProtocolFee = Math.mulDiv( \n tokensToTakeFromSender , \n ISmartCommitmentForwarder(SMART_COMMITMENT_FORWARDER)\n .getLiquidationProtocolFeePercent(),\n 10000) ;\n \n\n IERC20(principalToken).safeTransferFrom(\n msg.sender,\n address(this),\n amountDue + tokensToTakeFromSender - liquidationProtocolFee\n ); \n \n address protocolOwner = Ownable(address(TELLER_V2)).owner();\n\n IERC20(principalToken).safeTransferFrom(\n msg.sender,\n address(protocolOwner),\n liquidationProtocolFee\n );\n\n totalPrincipalTokensRepaid += amountDue;\n tokenDifferenceFromLiquidations += int256(tokensToTakeFromSender - liquidationProtocolFee );\n\n\n } else {\n \n \n uint256 tokensToGiveToSender = abs(minAmountDifference);\n\n \n IERC20(principalToken).safeTransferFrom(\n msg.sender,\n address(this),\n amountDue - tokensToGiveToSender \n );\n\n totalPrincipalTokensRepaid += amountDue;\n\n //this will make tokenDifference go more negative\n tokenDifferenceFromLiquidations -= int256(tokensToGiveToSender);\n\n \n }\n\n \n\n //this will give collateral to the caller\n ITellerV2(TELLER_V2).lenderCloseLoanWithRecipient(_bidId, msg.sender);\n \n \n emit DefaultedLoanLiquidated(\n _bidId,\n msg.sender,\n amountDue, \n _tokenAmountDifference\n );\n }\n\n\n function getLastUnpausedAt() \n public view \n returns (uint256) {\n\n\n return Math.max(\n lastUnpausedAt,\n IPausableTimestamp(SMART_COMMITMENT_FORWARDER).getLastUnpausedAt() //this counts tellerV2 pausing\n )\n ;\n \n\n }\n\n\n function setLastUnpausedAt() internal {\n lastUnpausedAt = block.timestamp;\n }\n\n \n\n function _getAmountOwedForBid(uint256 _bidId )\n internal\n view\n virtual\n returns (uint256 amountDue)\n {\n (,,,, amountDue, , , )\n = ITellerV2(TELLER_V2).getLoanSummary(_bidId);\n\n \n }\n\n\n function getTokenDifferenceFromLiquidations() public view returns (int256){\n\n return tokenDifferenceFromLiquidations;\n\n }\n \n\n /*\n This function will calculate the incentive amount (using a uniswap bonus plus a timer)\n of principal tokens that will be given to incentivize liquidating a loan \n \n */\n function getMinimumAmountDifferenceToCloseDefaultedLoan(\n uint256 _amountOwed,\n uint256 _loanDefaultedTimestamp\n ) public view virtual returns (int256 amountDifference_) {\n require(\n _loanDefaultedTimestamp > 0,\n \"Loan defaulted timestamp must be greater than zero\"\n );\n require(\n block.timestamp > _loanDefaultedTimestamp,\n \"Loan defaulted timestamp must be in the past\"\n );\n\n uint256 secondsSinceDefaulted = block.timestamp -\n _loanDefaultedTimestamp;\n\n //this starts at 764% and falls to -100% \n int256 incentiveMultiplier = int256(86400 - 10000) -\n int256(secondsSinceDefaulted);\n\n if (incentiveMultiplier < -10000) {\n incentiveMultiplier = -10000;\n }\n\n amountDifference_ =\n (int256(_amountOwed) * incentiveMultiplier) /\n int256(10000);\n }\n\n function abs(int x) private pure returns (uint) {\n return x >= 0 ? uint(x) : uint(-x);\n }\n\n\n function calculateCollateralRequiredToBorrowPrincipal( \n uint256 _principalAmount\n ) public\n view\n virtual\n returns (uint256) {\n\n uint256 baseAmount = calculateCollateralTokensAmountEquivalentToPrincipalTokens(\n _principalAmount\n ); \n\n //this is an amount of collateral\n return baseAmount.percent(collateralRatio);\n }\n\n\n //this is expanded by 10e18\n //this logic is very similar to that used in LCFA \n function calculateCollateralTokensAmountEquivalentToPrincipalTokens(\n uint256 principalAmount \n ) public view virtual returns (uint256 collateralTokensAmountToMatchValue) {\n \n uint256 pairPriceWithTwapFromOracle = UniswapPricingLibrary\n .getUniswapPriceRatioForPoolRoutes(poolOracleRoutes);\n \n \n uint256 principalPerCollateralAmount = maxPrincipalPerCollateralAmount == 0 \n ? pairPriceWithTwapFromOracle \n : Math.min(\n pairPriceWithTwapFromOracle,\n maxPrincipalPerCollateralAmount //this is expanded by uniswap exp factor \n ) ;\n\n\n return\n getRequiredCollateral(\n principalAmount,\n principalPerCollateralAmount \n );\n }\n\n\n\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount \n \n ) public view virtual returns (uint256) {\n \n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n STANDARD_EXPANSION_FACTOR,\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n ); \n }\n \n\n /*\n This callback occurs when a TellerV2 repayment happens or when a TellerV2 liquidate happens \n\n lenderCloseLoan does not trigger a repayLoanCallback \n */\n function repayLoanCallback(\n uint256 _bidId,\n address repayer,\n uint256 principalAmount,\n uint256 interestAmount\n ) external onlyTellerV2 whenForwarderNotPaused whenNotPaused {\n //can use principal amt to increment amt paid back!! nice for math .\n totalPrincipalTokensRepaid += principalAmount;\n totalInterestCollected += interestAmount;\n\n emit LoanRepaid(\n _bidId,\n repayer,\n principalAmount,\n interestAmount,\n totalPrincipalTokensRepaid,\n totalInterestCollected\n );\n }\n\n\n /*\n If principaltokens get stuck in the escrow vault for any reason, anyone may\n call this function to move them from that vault in to this contract \n */\n function withdrawFromEscrowVault ( uint256 _amount ) public whenForwarderNotPaused whenNotPaused {\n\n\n address _escrowVault = ITellerV2(TELLER_V2).getEscrowVault();\n\n IEscrowVault(_escrowVault).withdraw(address(principalToken), _amount );\n\n }\n \n \n function getTotalPrincipalTokensOutstandingInActiveLoans()\n public\n view\n returns (uint256)\n {\n return totalPrincipalTokensLended - totalPrincipalTokensRepaid;\n }\n\n\n\n\n function getCollateralTokenAddress() external view returns (address) {\n return address(collateralToken);\n }\n\n function getCollateralTokenId() external view returns (uint256) {\n return 0;\n }\n\n function getCollateralTokenType()\n external\n view\n returns (CommitmentCollateralType)\n {\n return CommitmentCollateralType.ERC20;\n }\n\n //this was a redundant function \n /* function getRequiredCollateral(uint256 _principalAmount)\n public\n view\n returns (uint256 requiredCollateral_)\n {\n requiredCollateral_ = getCollateralRequiredForPrincipalAmount(\n _principalAmount\n );\n }*/\n\n function getMarketId() external view returns (uint256) {\n return marketId;\n }\n\n function getMaxLoanDuration() external view returns (uint32) {\n return maxLoanDuration;\n }\n\n\n function getPoolUtilizationRatio(uint256 activeLoansAmountDelta ) public view returns (uint16) {\n\n if (getPoolTotalEstimatedValue() == 0) {\n return 0;\n }\n\n return uint16( Math.min( \n MathUpgradeable.mulDiv( \n (getTotalPrincipalTokensOutstandingInActiveLoans() + activeLoansAmountDelta), \n 10000 ,\n getPoolTotalEstimatedValue() ) , \n 10000 ));\n\n }\n\n function getMinInterestRate(uint256 amountDelta) public view returns (uint16) {\n return interestRateLowerBound + \n uint16( uint256(interestRateUpperBound-interestRateLowerBound)\n .percent(getPoolUtilizationRatio(amountDelta )\n \n ) );\n } \n \n\n function getPrincipalTokenAddress() external view returns (address) {\n return address(principalToken);\n }\n\n \n\n function getPrincipalAmountAvailableToBorrow()\n public\n view\n returns (uint256)\n { \n\n return ( uint256( getPoolTotalEstimatedValue() )).percent(liquidityThresholdPercent) -\n getTotalPrincipalTokensOutstandingInActiveLoans() ;\n \n }\n\n /**\n * @notice Lets the DAO/owner of the protocol implement an emergency stop mechanism.\n */\n function pauseLendingPool() public virtual onlyOwner whenNotPaused {\n _pause();\n }\n\n /**\n * @notice Lets the DAO/owner of the protocol undo a previously implemented emergency stop.\n */\n function unpauseLendingPool() public virtual onlyOwner whenPaused {\n setLastUnpausedAt();\n _unpause();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroupShares.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract LenderCommitmentGroupShares is ERC20, Ownable {\n uint8 private immutable DECIMALS;\n\n constructor(string memory _name, string memory _symbol, uint8 _decimals)\n ERC20(_name, _symbol)\n Ownable()\n {\n DECIMALS = _decimals;\n }\n\n function mint(address _recipient, uint256 _amount) external onlyOwner {\n _mint(_recipient, _amount);\n }\n\n function burn(address _burner, uint256 _amount) external onlyOwner {\n _burn(_burner, _amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return DECIMALS;\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_G1.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"../TellerV2MarketForwarder_G1.sol\";\n\n// Interfaces\nimport \"../interfaces/ICollateralManager.sol\";\nimport { Collateral, CollateralType } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\n\ncontract LenderCommitmentForwarder_G1 is TellerV2MarketForwarder_G1 {\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n enum CommitmentCollateralType {\n NONE, // no collateral required\n ERC20,\n ERC721,\n ERC1155,\n ERC721_ANY_ID,\n ERC1155_ANY_ID,\n ERC721_MERKLE_PROOF,\n ERC1155_MERKLE_PROOF\n }\n\n /**\n * @notice Details about a lender's capital commitment.\n * @param maxPrincipal Amount of tokens being committed by the lender. Max amount that can be loaned.\n * @param expiration Expiration time in seconds, when the commitment expires.\n * @param maxDuration Length of time, in seconds that the lender's capital can be lent out for.\n * @param minInterestRate Minimum Annual percentage to be applied for loans using the lender's capital.\n * @param collateralTokenAddress The address for the token contract that must be used to provide collateral for loans for this commitment.\n * @param maxPrincipalPerCollateralAmount The amount of principal that can be used for a loan per each unit of collateral, expanded additionally by principal decimals.\n * @param collateralTokenType The type of asset of the collateralTokenAddress (ERC20, ERC721, or ERC1155).\n * @param lender The address of the lender for this commitment.\n * @param marketId The market id for this commitment.\n * @param principalTokenAddress The address for the token contract that will be used to provide principal for loans of this commitment.\n */\n struct Commitment {\n uint256 maxPrincipal;\n uint32 expiration;\n uint32 maxDuration;\n uint16 minInterestRate;\n address collateralTokenAddress;\n uint256 collateralTokenId; //we use this for the MerkleRootHash for type ERC721_MERKLE_PROOF\n uint256 maxPrincipalPerCollateralAmount;\n CommitmentCollateralType collateralTokenType;\n address lender;\n uint256 marketId;\n address principalTokenAddress;\n }\n\n // CommitmentId => commitment\n mapping(uint256 => Commitment) public commitments;\n\n uint256 commitmentCount;\n\n //https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/structs/EnumerableSetUpgradeable.sol\n mapping(uint256 => EnumerableSetUpgradeable.AddressSet)\n internal commitmentBorrowersList;\n\n mapping(uint256 => uint256) public commitmentPrincipalAccepted;\n\n /**\n * @notice This event is emitted when a lender's commitment is created.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event CreatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when a lender's commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event UpdatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when the allowed borrowers for a commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n */\n event UpdatedCommitmentBorrowers(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment has been deleted.\n * @param commitmentId The id of the commitment that was deleted.\n */\n event DeletedCommitment(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment is exercised for a loan.\n * @param commitmentId The id of the commitment that was exercised.\n * @param borrower The address of the borrower.\n * @param tokenAmount The amount of the asset being committed.\n * @param bidId The bid id for the loan from TellerV2.\n */\n event ExercisedCommitment(\n uint256 indexed commitmentId,\n address borrower,\n uint256 tokenAmount,\n uint256 bidId\n );\n\n error InsufficientCommitmentAllocation(\n uint256 allocated,\n uint256 requested\n );\n error InsufficientBorrowerCollateral(uint256 required, uint256 actual);\n\n /** Modifiers **/\n\n modifier commitmentLender(uint256 _commitmentId) {\n require(\n commitments[_commitmentId].lender == _msgSender(),\n \"unauthorized commitment lender\"\n );\n _;\n }\n\n function validateCommitment(Commitment storage _commitment) internal {\n require(\n _commitment.expiration > uint32(block.timestamp),\n \"expired commitment\"\n );\n require(\n _commitment.maxPrincipal > 0,\n \"commitment principal allocation 0\"\n );\n\n if (_commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n require(\n _commitment.maxPrincipalPerCollateralAmount > 0,\n \"commitment collateral ratio 0\"\n );\n\n if (\n _commitment.collateralTokenType ==\n CommitmentCollateralType.ERC20\n ) {\n require(\n _commitment.collateralTokenId == 0,\n \"commitment collateral token id must be 0 for ERC20\"\n );\n }\n }\n }\n\n /** External Functions **/\n\n constructor(address _protocolAddress, address _marketRegistry)\n TellerV2MarketForwarder_G1(_protocolAddress, _marketRegistry)\n {}\n\n /**\n * @notice Creates a loan commitment from a lender for a market.\n * @param _commitment The new commitment data expressed as a struct\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n * @return commitmentId_ returns the commitmentId for the created commitment\n */\n function createCommitment(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList\n ) public returns (uint256 commitmentId_) {\n commitmentId_ = commitmentCount++;\n\n require(\n _commitment.lender == _msgSender(),\n \"unauthorized commitment creator\"\n );\n\n commitments[commitmentId_] = _commitment;\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitments[commitmentId_]);\n\n //the borrower allowlists is in a different storage space so we append them to the array with this method s\n _addBorrowersToCommitmentAllowlist(commitmentId_, _borrowerAddressList);\n\n emit CreatedCommitment(\n commitmentId_,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the commitment of a lender to a market.\n * @param _commitmentId The Id of the commitment to update.\n * @param _commitment The new commitment data expressed as a struct\n */\n function updateCommitment(\n uint256 _commitmentId,\n Commitment calldata _commitment\n ) public commitmentLender(_commitmentId) {\n require(\n _commitment.lender == _msgSender(),\n \"Commitment lender cannot be updated.\"\n );\n\n require(\n _commitment.principalTokenAddress ==\n commitments[_commitmentId].principalTokenAddress,\n \"Principal token address cannot be updated.\"\n );\n require(\n _commitment.marketId == commitments[_commitmentId].marketId,\n \"Market Id cannot be updated.\"\n );\n\n commitments[_commitmentId] = _commitment;\n\n //make sure the commitment data still adheres to required specifications and limits\n validateCommitment(commitments[_commitmentId]);\n\n emit UpdatedCommitment(\n _commitmentId,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function addCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _addBorrowersToCommitmentAllowlist(_commitmentId, _borrowerAddressList);\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function removeCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _removeBorrowersFromCommitmentAllowlist(\n _commitmentId,\n _borrowerAddressList\n );\n }\n\n /**\n * @notice Adds a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _addBorrowersToCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].add(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _removeBorrowersFromCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].remove(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes the commitment of a lender to a market.\n * @param _commitmentId The id of the commitment to delete.\n */\n function deleteCommitment(uint256 _commitmentId)\n public\n commitmentLender(_commitmentId)\n {\n delete commitments[_commitmentId];\n delete commitmentBorrowersList[_commitmentId];\n emit DeletedCommitment(_commitmentId);\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration\n ) external returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType <=\n CommitmentCollateralType.ERC1155_ANY_ID,\n \"Invalid commitment collateral type\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _interestRate,\n _loanDuration\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @param _merkleProof An array of bytes32 which are the roots down the merkle tree, the merkle proof.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) external returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF ||\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC1155_MERKLE_PROOF,\n \"Invalid commitment collateral type\"\n );\n\n bytes32 _merkleRoot = bytes32(\n commitments[_commitmentId].collateralTokenId\n );\n bytes32 _leaf = keccak256(abi.encodePacked(_collateralTokenId));\n\n //make sure collateral token id is a leaf within the proof\n require(\n MerkleProofUpgradeable.verifyCalldata(\n _merkleProof,\n _merkleRoot,\n _leaf\n ),\n \"Invalid proof\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _interestRate,\n _loanDuration\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function _acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration\n ) internal returns (uint256 bidId) {\n address borrower = _msgSender();\n\n Commitment storage commitment = commitments[_commitmentId];\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitment);\n\n //the collateral token of the commitment should be the same as the acceptor expects\n require(\n _collateralTokenAddress == commitment.collateralTokenAddress,\n \"Mismatching collateral token\"\n );\n //the interest rate must be at least as high has the commitment demands. The borrower can use a higher interest rate although that would not be beneficial to the borrower.\n require(\n _interestRate >= commitment.minInterestRate,\n \"Invalid interest rate\"\n );\n //the loan duration must be less than the commitment max loan duration. The lender who made the commitment expects the money to be returned before this window.\n require(\n _loanDuration <= commitment.maxDuration,\n \"Invalid loan max duration\"\n );\n\n require(\n commitmentPrincipalAccepted[bidId] <= commitment.maxPrincipal,\n \"Invalid loan max principal\"\n );\n\n require(\n commitmentBorrowersList[_commitmentId].length() == 0 ||\n commitmentBorrowersList[_commitmentId].contains(borrower),\n \"unauthorized commitment borrower\"\n );\n //require that the borrower accepting the commitment cannot borrow more than the commitments max principal\n if (_principalAmount > commitment.maxPrincipal) {\n revert InsufficientCommitmentAllocation({\n allocated: commitment.maxPrincipal,\n requested: _principalAmount\n });\n }\n\n uint256 requiredCollateral = getRequiredCollateral(\n _principalAmount,\n commitment.maxPrincipalPerCollateralAmount,\n commitment.collateralTokenType,\n commitment.collateralTokenAddress,\n commitment.principalTokenAddress\n );\n\n if (_collateralAmount < requiredCollateral) {\n revert InsufficientBorrowerCollateral({\n required: requiredCollateral,\n actual: _collateralAmount\n });\n }\n\n //ERC721 assets must have a quantity of 1\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_ANY_ID ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n require(\n _collateralAmount == 1,\n \"invalid commitment collateral amount for ERC721\"\n );\n }\n\n //ERC721 and ERC1155 types strictly enforce a specific token Id. ERC721_ANY and ERC1155_ANY do not.\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType == CommitmentCollateralType.ERC1155\n ) {\n require(\n commitment.collateralTokenId == _collateralTokenId,\n \"invalid commitment collateral tokenId\"\n );\n }\n\n commitmentPrincipalAccepted[_commitmentId] += _principalAmount;\n\n require(\n commitmentPrincipalAccepted[_commitmentId] <=\n commitment.maxPrincipal,\n \"Exceeds max principal of commitment\"\n );\n\n bidId = _submitBidFromCommitment(\n borrower,\n commitment.marketId,\n commitment.principalTokenAddress,\n _principalAmount,\n commitment.collateralTokenAddress,\n _collateralAmount,\n _collateralTokenId,\n commitment.collateralTokenType,\n _loanDuration,\n _interestRate\n );\n\n _acceptBid(bidId, commitment.lender);\n\n emit ExercisedCommitment(\n _commitmentId,\n borrower,\n _principalAmount,\n bidId\n );\n }\n\n /**\n * @notice Calculate the amount of collateral required to borrow a loan with _principalAmount of principal\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _maxPrincipalPerCollateralAmount The ratio for the amount of principal that can be borrowed for each amount of collateral. This is expanded additionally by the principal decimals.\n * @param _collateralTokenType The type of collateral for the loan either ERC20, ERC721, ERC1155, or None.\n * @param _collateralTokenAddress The contract address for the collateral for the loan.\n * @param _principalTokenAddress The contract address for the principal for the loan.\n */\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount,\n CommitmentCollateralType _collateralTokenType,\n address _collateralTokenAddress,\n address _principalTokenAddress\n ) public view virtual returns (uint256) {\n if (_collateralTokenType == CommitmentCollateralType.NONE) {\n return 0;\n }\n\n uint8 collateralDecimals;\n uint8 principalDecimals = IERC20MetadataUpgradeable(\n _principalTokenAddress\n ).decimals();\n\n if (_collateralTokenType == CommitmentCollateralType.ERC20) {\n collateralDecimals = IERC20MetadataUpgradeable(\n _collateralTokenAddress\n ).decimals();\n }\n\n /*\n * The principalAmount is expanded by (collateralDecimals+principalDecimals) to increase precision\n * and then it is divided by _maxPrincipalPerCollateralAmount which should already been expanded by principalDecimals\n */\n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n (10**(collateralDecimals + principalDecimals)),\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n );\n }\n\n /**\n * @notice Return the array of borrowers that are allowlisted for a commitment\n * @param _commitmentId The commitment id for the commitment to query.\n * @return borrowers_ An array of addresses restricted to accept the commitment. Empty array means unrestricted.\n */\n function getCommitmentBorrowers(uint256 _commitmentId)\n external\n view\n returns (address[] memory borrowers_)\n {\n borrowers_ = commitmentBorrowersList[_commitmentId].values();\n }\n\n /**\n * @notice Internal function to submit a bid to the lending protocol using a commitment\n * @param _borrower The address of the borrower for the loan.\n * @param _marketId The id for the market of the loan in the lending protocol.\n * @param _principalTokenAddress The contract address for the principal token.\n * @param _principalAmount The amount of principal to borrow for the loan.\n * @param _collateralTokenAddress The contract address for the collateral token.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId for the collateral (if it is ERC721 or ERC1155).\n * @param _collateralTokenType The type of collateral token (ERC20,ERC721,ERC1177,None).\n * @param _loanDuration The duration of the loan in seconds delta. Must be longer than loan payment cycle for the market.\n * @param _interestRate The amount of interest APY for the loan expressed in basis points.\n */\n function _submitBidFromCommitment(\n address _borrower,\n uint256 _marketId,\n address _principalTokenAddress,\n uint256 _principalAmount,\n address _collateralTokenAddress,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n CommitmentCollateralType _collateralTokenType,\n uint32 _loanDuration,\n uint16 _interestRate\n ) internal returns (uint256 bidId) {\n CreateLoanArgs memory createLoanArgs;\n createLoanArgs.marketId = _marketId;\n createLoanArgs.lendingToken = _principalTokenAddress;\n createLoanArgs.principal = _principalAmount;\n createLoanArgs.duration = _loanDuration;\n createLoanArgs.interestRate = _interestRate;\n\n Collateral[] memory collateralInfo;\n if (_collateralTokenType != CommitmentCollateralType.NONE) {\n collateralInfo = new Collateral[](1);\n collateralInfo[0] = Collateral({\n _collateralType: _getEscrowCollateralType(_collateralTokenType),\n _tokenId: _collateralTokenId,\n _amount: _collateralAmount,\n _collateralAddress: _collateralTokenAddress\n });\n }\n\n bidId = _submitBidWithCollateral(\n createLoanArgs,\n collateralInfo,\n _borrower\n );\n }\n\n /**\n * @notice Return the collateral type based on the commitmentcollateral type. Collateral type is used in the base lending protocol.\n * @param _type The type of collateral to be used for the loan.\n */\n function _getEscrowCollateralType(CommitmentCollateralType _type)\n internal\n pure\n returns (CollateralType)\n {\n if (_type == CommitmentCollateralType.ERC20) {\n return CollateralType.ERC20;\n }\n if (\n _type == CommitmentCollateralType.ERC721 ||\n _type == CommitmentCollateralType.ERC721_ANY_ID ||\n _type == CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n return CollateralType.ERC721;\n }\n if (\n _type == CommitmentCollateralType.ERC1155 ||\n _type == CommitmentCollateralType.ERC1155_ANY_ID ||\n _type == CommitmentCollateralType.ERC1155_MERKLE_PROOF\n ) {\n return CollateralType.ERC1155;\n }\n\n revert(\"Unknown Collateral Type\");\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_G2.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"../TellerV2MarketForwarder_G2.sol\";\n\n// Interfaces\nimport \"../interfaces/ICollateralManager.sol\";\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\nimport { Collateral, CollateralType } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\n\ncontract LenderCommitmentForwarder_G2 is\n TellerV2MarketForwarder_G2,\n ILenderCommitmentForwarder\n{\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n // CommitmentId => commitment\n mapping(uint256 => Commitment) public commitments;\n\n uint256 commitmentCount;\n\n //https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/structs/EnumerableSetUpgradeable.sol\n mapping(uint256 => EnumerableSetUpgradeable.AddressSet)\n internal commitmentBorrowersList;\n\n mapping(uint256 => uint256) public commitmentPrincipalAccepted;\n\n /**\n * @notice This event is emitted when a lender's commitment is created.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event CreatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when a lender's commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event UpdatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when the allowed borrowers for a commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n */\n event UpdatedCommitmentBorrowers(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment has been deleted.\n * @param commitmentId The id of the commitment that was deleted.\n */\n event DeletedCommitment(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment is exercised for a loan.\n * @param commitmentId The id of the commitment that was exercised.\n * @param borrower The address of the borrower.\n * @param tokenAmount The amount of the asset being committed.\n * @param bidId The bid id for the loan from TellerV2.\n */\n event ExercisedCommitment(\n uint256 indexed commitmentId,\n address borrower,\n uint256 tokenAmount,\n uint256 bidId\n );\n\n error InsufficientCommitmentAllocation(\n uint256 allocated,\n uint256 requested\n );\n error InsufficientBorrowerCollateral(uint256 required, uint256 actual);\n\n /** Modifiers **/\n\n modifier commitmentLender(uint256 _commitmentId) {\n require(\n commitments[_commitmentId].lender == _msgSender(),\n \"unauthorized commitment lender\"\n );\n _;\n }\n\n function validateCommitment(Commitment storage _commitment) internal {\n require(\n _commitment.expiration > uint32(block.timestamp),\n \"expired commitment\"\n );\n require(\n _commitment.maxPrincipal > 0,\n \"commitment principal allocation 0\"\n );\n\n if (_commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n require(\n _commitment.maxPrincipalPerCollateralAmount > 0,\n \"commitment collateral ratio 0\"\n );\n\n if (\n _commitment.collateralTokenType ==\n CommitmentCollateralType.ERC20\n ) {\n require(\n _commitment.collateralTokenId == 0,\n \"commitment collateral token id must be 0 for ERC20\"\n );\n }\n }\n }\n\n /** External Functions **/\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _protocolAddress, address _marketRegistry)\n TellerV2MarketForwarder_G2(_protocolAddress, _marketRegistry)\n {}\n\n /**\n * @notice Creates a loan commitment from a lender for a market.\n * @param _commitment The new commitment data expressed as a struct\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n * @return commitmentId_ returns the commitmentId for the created commitment\n */\n function createCommitment(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList\n ) public returns (uint256 commitmentId_) {\n commitmentId_ = commitmentCount++;\n\n require(\n _commitment.lender == _msgSender(),\n \"unauthorized commitment creator\"\n );\n\n commitments[commitmentId_] = _commitment;\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitments[commitmentId_]);\n\n //the borrower allowlists is in a different storage space so we append them to the array with this method s\n _addBorrowersToCommitmentAllowlist(commitmentId_, _borrowerAddressList);\n\n emit CreatedCommitment(\n commitmentId_,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the commitment of a lender to a market.\n * @param _commitmentId The Id of the commitment to update.\n * @param _commitment The new commitment data expressed as a struct\n */\n function updateCommitment(\n uint256 _commitmentId,\n Commitment calldata _commitment\n ) public commitmentLender(_commitmentId) {\n require(\n _commitment.lender == _msgSender(),\n \"Commitment lender cannot be updated.\"\n );\n\n require(\n _commitment.principalTokenAddress ==\n commitments[_commitmentId].principalTokenAddress,\n \"Principal token address cannot be updated.\"\n );\n require(\n _commitment.marketId == commitments[_commitmentId].marketId,\n \"Market Id cannot be updated.\"\n );\n\n commitments[_commitmentId] = _commitment;\n\n //make sure the commitment data still adheres to required specifications and limits\n validateCommitment(commitments[_commitmentId]);\n\n emit UpdatedCommitment(\n _commitmentId,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function addCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _addBorrowersToCommitmentAllowlist(_commitmentId, _borrowerAddressList);\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function removeCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _removeBorrowersFromCommitmentAllowlist(\n _commitmentId,\n _borrowerAddressList\n );\n }\n\n /**\n * @notice Adds a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _addBorrowersToCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].add(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _removeBorrowersFromCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].remove(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes the commitment of a lender to a market.\n * @param _commitmentId The id of the commitment to delete.\n */\n function deleteCommitment(uint256 _commitmentId)\n public\n commitmentLender(_commitmentId)\n {\n delete commitments[_commitmentId];\n delete commitmentBorrowersList[_commitmentId];\n emit DeletedCommitment(_commitmentId);\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType <=\n CommitmentCollateralType.ERC1155_ANY_ID,\n \"Invalid commitment collateral type\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n return\n acceptCommitmentWithRecipient(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n address(0),\n _interestRate,\n _loanDuration\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @param _merkleProof An array of bytes32 which are the roots down the merkle tree, the merkle proof.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF ||\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC1155_MERKLE_PROOF,\n \"Invalid commitment collateral type\"\n );\n\n bytes32 _merkleRoot = bytes32(\n commitments[_commitmentId].collateralTokenId\n );\n bytes32 _leaf = keccak256(abi.encodePacked(_collateralTokenId));\n\n //make sure collateral token id is a leaf within the proof\n require(\n MerkleProofUpgradeable.verifyCalldata(\n _merkleProof,\n _merkleRoot,\n _leaf\n ),\n \"Invalid proof\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function acceptCommitmentWithProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n return\n acceptCommitmentWithRecipientAndProof(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n address(0),\n _interestRate,\n _loanDuration,\n _merkleProof\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function _acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) internal returns (uint256 bidId) {\n Commitment storage commitment = commitments[_commitmentId];\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitment);\n\n //the collateral token of the commitment should be the same as the acceptor expects\n require(\n _collateralTokenAddress == commitment.collateralTokenAddress,\n \"Mismatching collateral token\"\n );\n //the interest rate must be at least as high has the commitment demands. The borrower can use a higher interest rate although that would not be beneficial to the borrower.\n require(\n _interestRate >= commitment.minInterestRate,\n \"Invalid interest rate\"\n );\n //the loan duration must be less than the commitment max loan duration. The lender who made the commitment expects the money to be returned before this window.\n require(\n _loanDuration <= commitment.maxDuration,\n \"Invalid loan max duration\"\n );\n\n require(\n commitmentPrincipalAccepted[bidId] <= commitment.maxPrincipal,\n \"Invalid loan max principal\"\n );\n\n require(\n commitmentBorrowersList[_commitmentId].length() == 0 ||\n commitmentBorrowersList[_commitmentId].contains(_msgSender()),\n \"unauthorized commitment borrower\"\n );\n //require that the borrower accepting the commitment cannot borrow more than the commitments max principal\n if (_principalAmount > commitment.maxPrincipal) {\n revert InsufficientCommitmentAllocation({\n allocated: commitment.maxPrincipal,\n requested: _principalAmount\n });\n }\n\n uint256 requiredCollateral = getRequiredCollateral(\n _principalAmount,\n commitment.maxPrincipalPerCollateralAmount,\n commitment.collateralTokenType,\n commitment.collateralTokenAddress,\n commitment.principalTokenAddress\n );\n\n if (_collateralAmount < requiredCollateral) {\n revert InsufficientBorrowerCollateral({\n required: requiredCollateral,\n actual: _collateralAmount\n });\n }\n\n //ERC721 assets must have a quantity of 1\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_ANY_ID ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n require(\n _collateralAmount == 1,\n \"invalid commitment collateral amount for ERC721\"\n );\n }\n\n //ERC721 and ERC1155 types strictly enforce a specific token Id. ERC721_ANY and ERC1155_ANY do not.\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType == CommitmentCollateralType.ERC1155\n ) {\n require(\n commitment.collateralTokenId == _collateralTokenId,\n \"invalid commitment collateral tokenId\"\n );\n }\n\n commitmentPrincipalAccepted[_commitmentId] += _principalAmount;\n\n require(\n commitmentPrincipalAccepted[_commitmentId] <=\n commitment.maxPrincipal,\n \"Exceeds max principal of commitment\"\n );\n\n CreateLoanArgs memory createLoanArgs;\n createLoanArgs.marketId = commitment.marketId;\n createLoanArgs.lendingToken = commitment.principalTokenAddress;\n createLoanArgs.principal = _principalAmount;\n createLoanArgs.duration = _loanDuration;\n createLoanArgs.interestRate = _interestRate;\n createLoanArgs.recipient = _recipient;\n if (commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n createLoanArgs.collateral = new Collateral[](1);\n createLoanArgs.collateral[0] = Collateral({\n _collateralType: _getEscrowCollateralType(\n commitment.collateralTokenType\n ),\n _tokenId: _collateralTokenId,\n _amount: _collateralAmount,\n _collateralAddress: commitment.collateralTokenAddress\n });\n }\n\n bidId = _submitBidWithCollateral(createLoanArgs, _msgSender());\n\n _acceptBid(bidId, commitment.lender);\n\n emit ExercisedCommitment(\n _commitmentId,\n _msgSender(),\n _principalAmount,\n bidId\n );\n }\n\n /**\n * @notice Calculate the amount of collateral required to borrow a loan with _principalAmount of principal\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _maxPrincipalPerCollateralAmount The ratio for the amount of principal that can be borrowed for each amount of collateral. This is expanded additionally by the principal decimals.\n * @param _collateralTokenType The type of collateral for the loan either ERC20, ERC721, ERC1155, or None.\n * @param _collateralTokenAddress The contract address for the collateral for the loan.\n * @param _principalTokenAddress The contract address for the principal for the loan.\n */\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount,\n CommitmentCollateralType _collateralTokenType,\n address _collateralTokenAddress,\n address _principalTokenAddress\n ) public view virtual returns (uint256) {\n if (_collateralTokenType == CommitmentCollateralType.NONE) {\n return 0;\n }\n\n uint8 collateralDecimals;\n uint8 principalDecimals = IERC20MetadataUpgradeable(\n _principalTokenAddress\n ).decimals();\n\n if (_collateralTokenType == CommitmentCollateralType.ERC20) {\n collateralDecimals = IERC20MetadataUpgradeable(\n _collateralTokenAddress\n ).decimals();\n }\n\n /*\n * The principalAmount is expanded by (collateralDecimals+principalDecimals) to increase precision\n * and then it is divided by _maxPrincipalPerCollateralAmount which should already been expanded by principalDecimals\n */\n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n (10**(collateralDecimals + principalDecimals)),\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n );\n }\n\n /**\n * @notice Return the array of borrowers that are allowlisted for a commitment\n * @param _commitmentId The commitment id for the commitment to query.\n * @return borrowers_ An array of addresses restricted to accept the commitment. Empty array means unrestricted.\n */\n function getCommitmentBorrowers(uint256 _commitmentId)\n external\n view\n returns (address[] memory borrowers_)\n {\n borrowers_ = commitmentBorrowersList[_commitmentId].values();\n }\n\n /**\n * @notice Return the collateral type based on the commitmentcollateral type. Collateral type is used in the base lending protocol.\n * @param _type The type of collateral to be used for the loan.\n */\n function _getEscrowCollateralType(CommitmentCollateralType _type)\n internal\n pure\n returns (CollateralType)\n {\n if (_type == CommitmentCollateralType.ERC20) {\n return CollateralType.ERC20;\n }\n if (\n _type == CommitmentCollateralType.ERC721 ||\n _type == CommitmentCollateralType.ERC721_ANY_ID ||\n _type == CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n return CollateralType.ERC721;\n }\n if (\n _type == CommitmentCollateralType.ERC1155 ||\n _type == CommitmentCollateralType.ERC1155_ANY_ID ||\n _type == CommitmentCollateralType.ERC1155_MERKLE_PROOF\n ) {\n return CollateralType.ERC1155;\n }\n\n revert(\"Unknown Collateral Type\");\n }\n\n function getCommitmentMarketId(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitments[_commitmentId].marketId;\n }\n\n function getCommitmentLender(uint256 _commitmentId)\n external\n view\n returns (address)\n {\n return commitments[_commitmentId].lender;\n }\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitmentPrincipalAccepted[_commitmentId];\n }\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitments[_commitmentId].maxPrincipal;\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_G3.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"./LenderCommitmentForwarder_G2.sol\";\nimport \"./extensions/ExtensionsContextUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract LenderCommitmentForwarder_G3 is\n LenderCommitmentForwarder_G2,\n ExtensionsContextUpgradeable\n{\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _tellerV2, address _marketRegistry)\n LenderCommitmentForwarder_G2(_tellerV2, _marketRegistry)\n {}\n\n function _msgSender()\n internal\n view\n virtual\n override(ContextUpgradeable, ExtensionsContextUpgradeable)\n returns (address sender)\n {\n return ExtensionsContextUpgradeable._msgSender();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_U1.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"../TellerV2MarketForwarder_G2.sol\";\n\n// Interfaces\nimport \"../interfaces/ICollateralManager.sol\";\nimport \"../interfaces/ILenderCommitmentForwarder_U1.sol\";\nimport \"./extensions/ExtensionsContextUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\n\nimport { Collateral, CollateralType } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\n\nimport \"../interfaces/uniswap/IUniswapV3Pool.sol\";\nimport \"../interfaces/uniswap/IUniswapV3Factory.sol\";\n\nimport \"../libraries/uniswap/TickMath.sol\";\nimport \"../libraries/uniswap/FixedPoint96.sol\";\nimport \"../libraries/uniswap/FullMath.sol\";\n\nimport \"../libraries/NumbersLib.sol\";\n\nimport \"./extensions/ExtensionsContextUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n\n\n/*\n\nOnly do decimal expansion if it is an ERC20 not anything else !! \n\n*/\n\ncontract LenderCommitmentForwarder_U1 is\n ExtensionsContextUpgradeable, //this should always be first for upgradeability\n TellerV2MarketForwarder_G2,\n ILenderCommitmentForwarder_U1\n{\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using NumbersLib for uint256;\n\n // CommitmentId => commitment\n mapping(uint256 => Commitment) public commitments;\n\n uint256 commitmentCount;\n\n //https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/structs/EnumerableSetUpgradeable.sol\n mapping(uint256 => EnumerableSetUpgradeable.AddressSet)\n internal commitmentBorrowersList;\n\n mapping(uint256 => uint256) public commitmentPrincipalAccepted;\n\n mapping(uint256 => PoolRouteConfig[]) internal commitmentUniswapPoolRoutes;\n\n mapping(uint256 => uint16) internal commitmentPoolOracleLtvRatio;\n\n //does not take a storage slot\n address immutable UNISWAP_V3_FACTORY;\n\n uint256 immutable STANDARD_EXPANSION_FACTOR = 1e18;\n\n /**\n * @notice This event is emitted when a lender's commitment is created.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event CreatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when a lender's commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event UpdatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when the allowed borrowers for a commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n */\n event UpdatedCommitmentBorrowers(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment has been deleted.\n * @param commitmentId The id of the commitment that was deleted.\n */\n event DeletedCommitment(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment is exercised for a loan.\n * @param commitmentId The id of the commitment that was exercised.\n * @param borrower The address of the borrower.\n * @param tokenAmount The amount of the asset being committed.\n * @param bidId The bid id for the loan from TellerV2.\n */\n event ExercisedCommitment(\n uint256 indexed commitmentId,\n address borrower,\n uint256 tokenAmount,\n uint256 bidId\n );\n\n error InsufficientCommitmentAllocation(\n uint256 allocated,\n uint256 requested\n );\n error InsufficientBorrowerCollateral(uint256 required, uint256 actual);\n\n /** Modifiers **/\n\n modifier commitmentLender(uint256 _commitmentId) {\n require(\n commitments[_commitmentId].lender == _msgSender(),\n \"unauthorized commitment lender\"\n );\n _;\n }\n\n function validateCommitment(Commitment storage _commitment) internal {\n require(\n _commitment.expiration > uint32(block.timestamp),\n \"expired commitment\"\n );\n require(\n _commitment.maxPrincipal > 0,\n \"commitment principal allocation 0\"\n );\n\n if (_commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n require(\n _commitment.maxPrincipalPerCollateralAmount > 0,\n \"commitment collateral ratio 0\"\n );\n\n if (\n _commitment.collateralTokenType ==\n CommitmentCollateralType.ERC20\n ) {\n require(\n _commitment.collateralTokenId == 0,\n \"commitment collateral token id must be 0 for ERC20\"\n );\n }\n }\n }\n\n /** External Functions **/\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _protocolAddress,\n address _marketRegistry,\n address _uniswapV3Factory\n ) TellerV2MarketForwarder_G2(_protocolAddress, _marketRegistry) {\n UNISWAP_V3_FACTORY = _uniswapV3Factory;\n }\n\n /**\n * @notice Creates a loan commitment from a lender for a market.\n * @param _commitment The new commitment data expressed as a struct\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n * @return commitmentId_ returns the commitmentId for the created commitment\n */\n function createCommitmentWithUniswap(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList,\n PoolRouteConfig[] calldata _poolRoutes,\n uint16 _poolOracleLtvRatio //generally always between 0 and 100 % , 0 to 10000\n ) public returns (uint256 commitmentId_) {\n commitmentId_ = commitmentCount++;\n \n require(\n _commitment.lender == _msgSender(),\n \"unauthorized commitment creator\"\n );\n\n commitments[commitmentId_] = _commitment;\n\n require(_poolRoutes.length == 0 || _commitment.collateralTokenType == CommitmentCollateralType.ERC20 , \"can only use pool routes with ERC20 collateral\");\n\n\n //routes length of 0 means ignore price oracle limits\n require(_poolRoutes.length <= 2, \"invalid pool routes length\");\n\n \n \n\n for (uint256 i = 0; i < _poolRoutes.length; i++) {\n commitmentUniswapPoolRoutes[commitmentId_].push(_poolRoutes[i]);\n }\n\n commitmentPoolOracleLtvRatio[commitmentId_] = _poolOracleLtvRatio;\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitments[commitmentId_]);\n\n //the borrower allowlists is in a different storage space so we append them to the array with this method s\n _addBorrowersToCommitmentAllowlist(commitmentId_, _borrowerAddressList);\n\n emit CreatedCommitment(\n commitmentId_,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the commitment of a lender to a market.\n * @param _commitmentId The Id of the commitment to update.\n * @param _commitment The new commitment data expressed as a struct\n */\n function updateCommitment(\n uint256 _commitmentId,\n Commitment calldata _commitment\n ) public commitmentLender(_commitmentId) {\n require(\n _commitment.lender == _msgSender(),\n \"Commitment lender cannot be updated.\"\n );\n\n require(\n _commitment.principalTokenAddress ==\n commitments[_commitmentId].principalTokenAddress,\n \"Principal token address cannot be updated.\"\n );\n require(\n _commitment.marketId == commitments[_commitmentId].marketId,\n \"Market Id cannot be updated.\"\n );\n\n commitments[_commitmentId] = _commitment;\n\n //make sure the commitment data still adheres to required specifications and limits\n validateCommitment(commitments[_commitmentId]);\n\n emit UpdatedCommitment(\n _commitmentId,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function addCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _addBorrowersToCommitmentAllowlist(_commitmentId, _borrowerAddressList);\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function removeCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _removeBorrowersFromCommitmentAllowlist(\n _commitmentId,\n _borrowerAddressList\n );\n }\n\n /**\n * @notice Adds a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _addBorrowersToCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].add(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _removeBorrowersFromCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].remove(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes the commitment of a lender to a market.\n * @param _commitmentId The id of the commitment to delete.\n */\n function deleteCommitment(uint256 _commitmentId)\n public\n commitmentLender(_commitmentId)\n {\n delete commitments[_commitmentId];\n delete commitmentBorrowersList[_commitmentId];\n emit DeletedCommitment(_commitmentId);\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType <=\n CommitmentCollateralType.ERC1155_ANY_ID,\n \"Invalid commitment collateral type\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n return\n acceptCommitmentWithRecipient(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n address(0),\n _interestRate,\n _loanDuration\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @param _merkleProof An array of bytes32 which are the roots down the merkle tree, the merkle proof.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF ||\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC1155_MERKLE_PROOF,\n \"Invalid commitment collateral type\"\n );\n\n bytes32 _merkleRoot = bytes32(\n commitments[_commitmentId].collateralTokenId\n );\n bytes32 _leaf = keccak256(abi.encodePacked(_collateralTokenId));\n\n //make sure collateral token id is a leaf within the proof\n require(\n MerkleProofUpgradeable.verifyCalldata(\n _merkleProof,\n _merkleRoot,\n _leaf\n ),\n \"Invalid proof\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function acceptCommitmentWithProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n return\n acceptCommitmentWithRecipientAndProof(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n address(0),\n _interestRate,\n _loanDuration,\n _merkleProof\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function _acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) internal returns (uint256 bidId) {\n Commitment storage commitment = commitments[_commitmentId];\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitment);\n\n //the collateral token of the commitment should be the same as the acceptor expects\n require(\n _collateralTokenAddress == commitment.collateralTokenAddress,\n \"Mismatching collateral token\"\n );\n\n //the interest rate must be at least as high has the commitment demands. The borrower can use a higher interest rate although that would not be beneficial to the borrower.\n require(\n _interestRate >= commitment.minInterestRate,\n \"Invalid interest rate\"\n );\n //the loan duration must be less than the commitment max loan duration. The lender who made the commitment expects the money to be returned before this window.\n require(\n _loanDuration <= commitment.maxDuration,\n \"Invalid loan max duration\"\n );\n\n require(\n commitmentPrincipalAccepted[bidId] <= commitment.maxPrincipal,\n \"Invalid loan max principal\"\n );\n\n require(\n commitmentBorrowersList[_commitmentId].length() == 0 ||\n commitmentBorrowersList[_commitmentId].contains(_msgSender()),\n \"unauthorized commitment borrower\"\n );\n //require that the borrower accepting the commitment cannot borrow more than the commitments max principal\n if (_principalAmount > commitment.maxPrincipal) {\n revert InsufficientCommitmentAllocation({\n allocated: commitment.maxPrincipal,\n requested: _principalAmount\n });\n }\n\n {\n uint256 scaledPoolOraclePrice = getUniswapPriceRatioForPoolRoutes(\n commitmentUniswapPoolRoutes[_commitmentId]\n ).percent(commitmentPoolOracleLtvRatio[_commitmentId]);\n\n bool usePoolRoutes = commitmentUniswapPoolRoutes[_commitmentId]\n .length > 0;\n\n //use the worst case ratio either the oracle or the static ratio\n uint256 maxPrincipalPerCollateralAmount = usePoolRoutes\n ? Math.min(\n scaledPoolOraclePrice,\n commitment.maxPrincipalPerCollateralAmount\n )\n : commitment.maxPrincipalPerCollateralAmount;\n\n uint256 requiredCollateral = getRequiredCollateral(\n _principalAmount,\n maxPrincipalPerCollateralAmount,\n commitment.collateralTokenType\n );\n\n if (_collateralAmount < requiredCollateral) {\n revert InsufficientBorrowerCollateral({\n required: requiredCollateral,\n actual: _collateralAmount\n });\n }\n }\n\n //ERC721 assets must have a quantity of 1\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_ANY_ID ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n require(\n _collateralAmount == 1,\n \"invalid commitment collateral amount for ERC721\"\n );\n }\n\n //ERC721 and ERC1155 types strictly enforce a specific token Id. ERC721_ANY and ERC1155_ANY do not.\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType == CommitmentCollateralType.ERC1155\n ) {\n require(\n commitment.collateralTokenId == _collateralTokenId,\n \"invalid commitment collateral tokenId\"\n );\n }\n\n commitmentPrincipalAccepted[_commitmentId] += _principalAmount;\n\n require(\n commitmentPrincipalAccepted[_commitmentId] <=\n commitment.maxPrincipal,\n \"Exceeds max principal of commitment\"\n );\n\n CreateLoanArgs memory createLoanArgs;\n createLoanArgs.marketId = commitment.marketId;\n createLoanArgs.lendingToken = commitment.principalTokenAddress;\n createLoanArgs.principal = _principalAmount;\n createLoanArgs.duration = _loanDuration;\n createLoanArgs.interestRate = _interestRate;\n createLoanArgs.recipient = _recipient;\n if (commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n createLoanArgs.collateral = new Collateral[](1);\n createLoanArgs.collateral[0] = Collateral({\n _collateralType: _getEscrowCollateralType(\n commitment.collateralTokenType\n ),\n _tokenId: _collateralTokenId,\n _amount: _collateralAmount,\n _collateralAddress: commitment.collateralTokenAddress\n });\n }\n\n bidId = _submitBidWithCollateral(createLoanArgs, _msgSender());\n\n _acceptBid(bidId, commitment.lender);\n\n emit ExercisedCommitment(\n _commitmentId,\n _msgSender(),\n _principalAmount,\n bidId\n );\n }\n\n /**\n * @notice Calculate the amount of collateral required to borrow a loan with _principalAmount of principal\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _maxPrincipalPerCollateralAmount The ratio for the amount of principal that can be borrowed for each amount of collateral. \n * @param _collateralTokenType The type of collateral for the loan either ERC20, ERC721, ERC1155, or None.\n \n */\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount,\n CommitmentCollateralType _collateralTokenType\n ) public view virtual returns (uint256) {\n if (_collateralTokenType == CommitmentCollateralType.NONE) {\n return 0;\n }\n\n if (_collateralTokenType == CommitmentCollateralType.ERC20) {\n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n STANDARD_EXPANSION_FACTOR,\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n );\n }\n\n //for NFTs, do not use the uniswap expansion factor \n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n 1,\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n );\n\n \n }\n\n /**\n * @dev Returns the PoolRouteConfig at a specific index for a given commitmentId from the commitmentUniswapPoolRoutes mapping.\n * @param commitmentId The commitmentId to access the mapping.\n * @param index The index in the array of PoolRouteConfigs for the given commitmentId.\n * @return The PoolRouteConfig at the specified index.\n */\n function getCommitmentUniswapPoolRoute(uint256 commitmentId, uint index)\n public\n view\n returns (PoolRouteConfig memory)\n {\n require(\n index < commitmentUniswapPoolRoutes[commitmentId].length,\n \"Index out of bounds\"\n );\n return commitmentUniswapPoolRoutes[commitmentId][index];\n }\n\n /**\n * @dev Returns the entire array of PoolRouteConfigs for a given commitmentId from the commitmentUniswapPoolRoutes mapping.\n * @param commitmentId The commitmentId to access the mapping.\n * @return The entire array of PoolRouteConfigs for the specified commitmentId.\n */\n function getAllCommitmentUniswapPoolRoutes(uint256 commitmentId)\n public\n view\n returns (PoolRouteConfig[] memory)\n {\n return commitmentUniswapPoolRoutes[commitmentId];\n }\n\n /**\n * @dev Returns the uint16 value for a given commitmentId from the commitmentPoolOracleLtvRatio mapping.\n * @param commitmentId The key to access the mapping.\n * @return The uint16 value for the specified commitmentId.\n */\n function getCommitmentPoolOracleLtvRatio(uint256 commitmentId)\n public\n view\n returns (uint16)\n {\n return commitmentPoolOracleLtvRatio[commitmentId];\n }\n\n // ---- TWAP\n\n function getUniswapV3PoolAddress(\n address _principalTokenAddress,\n address _collateralTokenAddress,\n uint24 _uniswapPoolFee\n ) public view returns (address) {\n return\n IUniswapV3Factory(UNISWAP_V3_FACTORY).getPool(\n _principalTokenAddress,\n _collateralTokenAddress,\n _uniswapPoolFee\n );\n }\n\n /*\n \n This returns a price ratio which to be normalized, must be divided by STANDARD_EXPANSION_FACTOR\n\n */\n\n function getUniswapPriceRatioForPoolRoutes(\n PoolRouteConfig[] memory poolRoutes\n ) public view returns (uint256 priceRatio) {\n require(poolRoutes.length <= 2, \"invalid pool routes length\");\n\n if (poolRoutes.length == 2) {\n uint256 pool0PriceRatio = getUniswapPriceRatioForPool(\n poolRoutes[0]\n );\n\n uint256 pool1PriceRatio = getUniswapPriceRatioForPool(\n poolRoutes[1]\n );\n\n return\n FullMath.mulDiv(\n pool0PriceRatio,\n pool1PriceRatio,\n STANDARD_EXPANSION_FACTOR\n );\n } else if (poolRoutes.length == 1) {\n return getUniswapPriceRatioForPool(poolRoutes[0]);\n }\n\n //else return 0\n }\n\n /*\n The resultant product is expanded by STANDARD_EXPANSION_FACTOR one time \n */\n function getUniswapPriceRatioForPool(\n PoolRouteConfig memory _poolRouteConfig\n ) public view returns (uint256 priceRatio) {\n uint160 sqrtPriceX96 = getSqrtTwapX96(\n _poolRouteConfig.pool,\n _poolRouteConfig.twapInterval\n );\n\n //This is the token 1 per token 0 price\n uint256 sqrtPrice = FullMath.mulDiv(\n sqrtPriceX96,\n STANDARD_EXPANSION_FACTOR,\n 2**96\n );\n\n uint256 sqrtPriceInverse = (STANDARD_EXPANSION_FACTOR *\n STANDARD_EXPANSION_FACTOR) / sqrtPrice;\n\n uint256 price = _poolRouteConfig.zeroForOne\n ? sqrtPrice * sqrtPrice\n : sqrtPriceInverse * sqrtPriceInverse;\n\n return price / STANDARD_EXPANSION_FACTOR;\n }\n\n function getSqrtTwapX96(address uniswapV3Pool, uint32 twapInterval)\n internal\n view\n returns (uint160 sqrtPriceX96)\n {\n if (twapInterval == 0) {\n // return the current price if twapInterval == 0\n (sqrtPriceX96, , , , , , ) = IUniswapV3Pool(uniswapV3Pool).slot0();\n } else {\n uint32[] memory secondsAgos = new uint32[](2);\n secondsAgos[0] = twapInterval + 1; // from (before)\n secondsAgos[1] = 1; // one block prior\n\n (int56[] memory tickCumulatives, ) = IUniswapV3Pool(uniswapV3Pool)\n .observe(secondsAgos);\n\n // tick(imprecise as it's an integer) to price\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(\n int24(\n (tickCumulatives[1] - tickCumulatives[0]) /\n int32(twapInterval)\n )\n );\n }\n }\n\n function getPriceX96FromSqrtPriceX96(uint160 sqrtPriceX96)\n internal\n pure\n returns (uint256 priceX96)\n {\n return FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96);\n }\n\n // -----\n\n /**\n * @notice Return the array of borrowers that are allowlisted for a commitment\n * @param _commitmentId The commitment id for the commitment to query.\n * @return borrowers_ An array of addresses restricted to accept the commitment. Empty array means unrestricted.\n */\n function getCommitmentBorrowers(uint256 _commitmentId)\n external\n view\n returns (address[] memory borrowers_)\n {\n borrowers_ = commitmentBorrowersList[_commitmentId].values();\n }\n\n /**\n * @notice Return the collateral type based on the commitmentcollateral type. Collateral type is used in the base lending protocol.\n * @param _type The type of collateral to be used for the loan.\n */\n function _getEscrowCollateralType(CommitmentCollateralType _type)\n internal\n pure\n returns (CollateralType)\n {\n if (_type == CommitmentCollateralType.ERC20) {\n return CollateralType.ERC20;\n }\n if (\n _type == CommitmentCollateralType.ERC721 ||\n _type == CommitmentCollateralType.ERC721_ANY_ID ||\n _type == CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n return CollateralType.ERC721;\n }\n if (\n _type == CommitmentCollateralType.ERC1155 ||\n _type == CommitmentCollateralType.ERC1155_ANY_ID ||\n _type == CommitmentCollateralType.ERC1155_MERKLE_PROOF\n ) {\n return CollateralType.ERC1155;\n }\n\n revert(\"Unknown Collateral Type\");\n }\n\n function getCommitmentMarketId(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitments[_commitmentId].marketId;\n }\n\n function getCommitmentLender(uint256 _commitmentId)\n external\n view\n returns (address)\n {\n return commitments[_commitmentId].lender;\n }\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitmentPrincipalAccepted[_commitmentId];\n }\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitments[_commitmentId].maxPrincipal;\n }\n\n function getCommitmentPrincipalTokenAddress(uint256 _commitmentId)\n external\n view\n returns (address)\n {\n return commitments[_commitmentId].principalTokenAddress;\n }\n\n function getCommitmentCollateralTokenAddress(uint256 _commitmentId)\n external\n view\n returns (address)\n {\n return commitments[_commitmentId].collateralTokenAddress;\n }\n\n\n\n //Overrides\n function _msgSender()\n internal\n view\n virtual\n override(ContextUpgradeable, ExtensionsContextUpgradeable)\n returns (address sender)\n {\n return ExtensionsContextUpgradeable._msgSender();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"./LenderCommitmentForwarder_G1.sol\";\n\ncontract LenderCommitmentForwarder is LenderCommitmentForwarder_G1 {\n constructor(address _tellerV2, address _marketRegistry)\n LenderCommitmentForwarder_G1(_tellerV2, _marketRegistry)\n {\n _disableInitializers();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarderAlpha.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"./LenderCommitmentForwarder_U1.sol\";\n\ncontract LenderCommitmentForwarderAlpha is LenderCommitmentForwarder_U1 {\n constructor(\n address _tellerV2,\n address _marketRegistry,\n address _uniswapV3Factory\n )\n LenderCommitmentForwarder_U1(\n _tellerV2,\n _marketRegistry,\n _uniswapV3Factory\n )\n {\n // we only want this on an proxy deployment so it only affects the impl\n _disableInitializers();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarderStaging.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"./LenderCommitmentForwarder_G3.sol\";\n\ncontract LenderCommitmentForwarderStaging is\n ILenderCommitmentForwarder,\n LenderCommitmentForwarder_G3\n{\n constructor(address _tellerV2, address _marketRegistry)\n LenderCommitmentForwarder_G3(_tellerV2, _marketRegistry)\n {\n // we only want this on an proxy deployment so it only affects the impl\n _disableInitializers();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LoanReferralForwarder.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../interfaces/ITellerV2.sol\";\nimport \"../interfaces/IProtocolFee.sol\";\nimport \"../interfaces/ITellerV2Storage.sol\";\nimport \"../interfaces/IMarketRegistry.sol\"; \nimport \"../interfaces/ISmartCommitment.sol\";\nimport \"../interfaces/ISmartCommitmentForwarder.sol\";\nimport \"../interfaces/IFlashRolloverLoan_G4.sol\";\nimport \"../libraries/NumbersLib.sol\";\n\nimport { ILenderCommitmentForwarder } from \"../interfaces/ILenderCommitmentForwarder.sol\";\n \nimport { ILenderCommitmentForwarder_U1 } from \"../interfaces/ILenderCommitmentForwarder_U1.sol\";\n\n\n\n\ncontract LoanReferralForwarder \n {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n \n \n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n address smartCommitmentAddress; //if this is not address(0), we will use this ! leave empty if not used. \n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n \n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2 \n \n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n \n }\n\n \n\n /*\n \n */\n function acceptCommitmentWithReferral(\n address _commitmentForwarder, //leave 0 if using smart commitment address\n \n \n AcceptCommitmentArgs calldata _acceptCommitmentArgs ,\n \n \n address _recipient,\n uint256 _reward,\n address _rewardRecipient\n\n ) external returns (uint256 bidId_) {\n\n \n address principalTokenAddress = address(0);\n uint256 balanceBefore;\n\n \n require(_reward <= _acceptCommitmentArgs.principalAmount / 10, \"Reward can be no more than 10% of principal\");\n\n if (_acceptCommitmentArgs.smartCommitmentAddress != address(0)) {\n\n \n principalTokenAddress = ISmartCommitment(_acceptCommitmentArgs.smartCommitmentAddress).getPrincipalTokenAddress ();\n \n // Accept commitment and receive funds to this contract\n balanceBefore = IERC20(principalTokenAddress).balanceOf(address(this));\n \n bidId_ = _acceptSmartCommitmentWithRecipient(\n _commitmentForwarder,\n _acceptCommitmentArgs\n\n );\n\n \n }else{ \n principalTokenAddress = ILenderCommitmentForwarder_U1(_commitmentForwarder)\n .getCommitmentPrincipalTokenAddress (_acceptCommitmentArgs.commitmentId);\n \n // Accept commitment and receive funds to this contract\n balanceBefore = IERC20(principalTokenAddress).balanceOf(address(this));\n \n\n bidId_ = _acceptCommitmentWithRecipient(\n _commitmentForwarder,\n _acceptCommitmentArgs\n\n ); \n\n\n\n }\n \n uint256 balanceAfter = IERC20(principalTokenAddress).balanceOf(address(this));\n\n uint256 fundsRemaining = balanceAfter - balanceBefore;\n\n // require( fundsRemaining >= _minAmountReceived, \"Insufficient funds received\" );\n\n \n IERC20Upgradeable(principalTokenAddress).transfer(\n _rewardRecipient,\n _reward\n );\n\n IERC20Upgradeable(principalTokenAddress).transfer(\n _recipient,\n fundsRemaining - _reward\n );\n\n\n\n \n }\n\n\n function _acceptSmartCommitmentWithRecipient( \n address _smartCommitmentForwarder,\n AcceptCommitmentArgs calldata _acceptCommitmentArgs \n \n\n ) internal returns (uint256 bidId_) {\n\n bytes memory responseData = address(_smartCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ISmartCommitmentForwarder\n .acceptSmartCommitmentWithRecipient\n .selector,\n _acceptCommitmentArgs.smartCommitmentAddress,\n _acceptCommitmentArgs.principalAmount,\n _acceptCommitmentArgs.collateralAmount,\n _acceptCommitmentArgs.collateralTokenId,\n _acceptCommitmentArgs.collateralTokenAddress,\n address(this),\n _acceptCommitmentArgs.interestRate,\n _acceptCommitmentArgs.loanDuration\n ),\n msg.sender // borrower \n )\n );\n\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n\n\n }\n\n\n\n function _acceptCommitmentWithRecipient(\n address _commitmentForwarder,\n AcceptCommitmentArgs calldata _acceptCommitmentArgs \n \n\n ) internal returns (uint256 bidId_) {\n\n bytes memory responseData = address(_commitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _acceptCommitmentArgs.commitmentId,\n _acceptCommitmentArgs.principalAmount,\n _acceptCommitmentArgs.collateralAmount,\n _acceptCommitmentArgs.collateralTokenId,\n _acceptCommitmentArgs.collateralTokenAddress,\n address(this),\n _acceptCommitmentArgs.interestRate,\n _acceptCommitmentArgs.loanDuration\n ),\n msg.sender //borrower \n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n\n }\n\n \n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}" + }, + "contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../TellerV2MarketForwarder_G3.sol\";\nimport \"./extensions/ExtensionsContextUpgradeable.sol\";\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../interfaces/ISmartCommitmentForwarder.sol\";\nimport \"./LenderCommitmentForwarder_G1.sol\";\n\nimport \"../interfaces/IPausableTimestamp.sol\";\n\nimport \"../interfaces/IHasProtocolPausingManager.sol\";\n\nimport \"../interfaces/IProtocolPausingManager.sol\";\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\n\n\nimport { CommitmentCollateralType, ISmartCommitment } from \"../interfaces/ISmartCommitment.sol\";\n\n \ncontract SmartCommitmentForwarder is\n ExtensionsContextUpgradeable, //this should always be first for upgradeability\n TellerV2MarketForwarder_G3,\n PausableUpgradeable, //this does add some storage but AFTER all other storage\n ISmartCommitmentForwarder,\n IPausableTimestamp\n {\n\n using MathUpgradeable for uint256;\n\n event ExercisedSmartCommitment(\n address indexed smartCommitmentAddress,\n address borrower,\n uint256 tokenAmount,\n uint256 bidId\n );\n\n error InsufficientBorrowerCollateral(uint256 required, uint256 actual);\n\n\n\n modifier onlyProtocolPauser() { \n\n address pausingManager = IHasProtocolPausingManager( _tellerV2 ).getProtocolPausingManager();\n require( IProtocolPausingManager( pausingManager ).isPauser(_msgSender()) , \"Sender not authorized\");\n _;\n }\n\n\n modifier onlyProtocolOwner() { \n require( Ownable( _tellerV2 ).owner() == _msgSender() , \"Sender not authorized\");\n _;\n }\n\n uint256 public liquidationProtocolFeePercent; \n uint256 internal lastUnpausedAt;\n\n\n constructor(address _protocolAddress, address _marketRegistry)\n TellerV2MarketForwarder_G3(_protocolAddress, _marketRegistry)\n { }\n\n function initialize() public initializer { \n __Pausable_init();\n }\n\n function setLiquidationProtocolFeePercent(uint256 _percent) \n public onlyProtocolOwner { \n //max is 100% \n require( _percent <= 10000 , \"invalid fee percent\" );\n liquidationProtocolFeePercent = _percent;\n }\n\n function getLiquidationProtocolFeePercent() \n public view returns (uint256){ \n return liquidationProtocolFeePercent ;\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _smartCommitmentAddress The address of the smart commitment contract.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptSmartCommitmentWithRecipient(\n address _smartCommitmentAddress,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public whenNotPaused returns (uint256 bidId) {\n require(\n ISmartCommitment(_smartCommitmentAddress)\n .getCollateralTokenType() <=\n CommitmentCollateralType.ERC1155_ANY_ID,\n \"Invalid commitment collateral type\"\n );\n\n return\n _acceptCommitment(\n _smartCommitmentAddress,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function _acceptCommitment(\n address _smartCommitmentAddress,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) internal returns (uint256 bidId) {\n ISmartCommitment _commitment = ISmartCommitment(\n _smartCommitmentAddress\n );\n\n CreateLoanArgs memory createLoanArgs;\n\n createLoanArgs.marketId = _commitment.getMarketId();\n createLoanArgs.lendingToken = _commitment.getPrincipalTokenAddress();\n createLoanArgs.principal = _principalAmount;\n createLoanArgs.duration = _loanDuration;\n createLoanArgs.interestRate = _interestRate;\n createLoanArgs.recipient = _recipient;\n\n CommitmentCollateralType commitmentCollateralTokenType = _commitment\n .getCollateralTokenType();\n\n if (commitmentCollateralTokenType != CommitmentCollateralType.NONE) {\n createLoanArgs.collateral = new Collateral[](1);\n createLoanArgs.collateral[0] = Collateral({\n _collateralType: _getEscrowCollateralType(\n commitmentCollateralTokenType\n ),\n _tokenId: _collateralTokenId,\n _amount: _collateralAmount,\n _collateralAddress: _collateralTokenAddress // commitment.collateralTokenAddress\n });\n }\n\n bidId = _submitBidWithCollateral(createLoanArgs, _msgSender());\n\n _commitment.acceptFundsForAcceptBid(\n _msgSender(), //borrower\n bidId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenAddress,\n _collateralTokenId,\n _loanDuration,\n _interestRate\n );\n\n emit ExercisedSmartCommitment(\n _smartCommitmentAddress,\n _msgSender(),\n _principalAmount,\n bidId\n );\n }\n\n /**\n * @notice Return the collateral type based on the commitmentcollateral type. Collateral type is used in the base lending protocol.\n * @param _type The type of collateral to be used for the loan.\n */\n function _getEscrowCollateralType(CommitmentCollateralType _type)\n internal\n pure\n returns (CollateralType)\n {\n if (_type == CommitmentCollateralType.ERC20) {\n return CollateralType.ERC20;\n }\n if (\n _type == CommitmentCollateralType.ERC721 ||\n _type == CommitmentCollateralType.ERC721_ANY_ID ||\n _type == CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n return CollateralType.ERC721;\n }\n if (\n _type == CommitmentCollateralType.ERC1155 ||\n _type == CommitmentCollateralType.ERC1155_ANY_ID ||\n _type == CommitmentCollateralType.ERC1155_MERKLE_PROOF\n ) {\n return CollateralType.ERC1155;\n }\n\n revert(\"Unknown Collateral Type\");\n }\n\n\n\n /**\n * @notice Lets the DAO/owner of the protocol implement an emergency stop mechanism.\n */\n function pause() public virtual onlyProtocolPauser whenNotPaused {\n _pause();\n }\n\n /**\n * @notice Lets the DAO/owner of the protocol undo a previously implemented emergency stop.\n */\n function unpause() public virtual onlyProtocolPauser whenPaused {\n setLastUnpausedAt();\n _unpause();\n }\n\n\n function getLastUnpausedAt() \n public view \n returns (uint256) {\n\n\n address pausingManager = IHasProtocolPausingManager( _tellerV2 ).getProtocolPausingManager();\n \n return MathUpgradeable.max(\n lastUnpausedAt,\n IPausableTimestamp(pausingManager).getLastUnpausedAt()\n )\n ;\n \n\n }\n\n\n function setLastUnpausedAt() internal {\n lastUnpausedAt = block.timestamp;\n }\n\n\n // -----\n\n //Overrides\n function _msgSender()\n internal\n view\n virtual\n override(ContextUpgradeable, ExtensionsContextUpgradeable)\n returns (address sender)\n {\n return ExtensionsContextUpgradeable._msgSender();\n }\n \n}\n" + }, + "contracts/LenderManager.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\";\n\n// Interfaces\nimport \"./interfaces/ILenderManager.sol\";\nimport \"./interfaces/ITellerV2.sol\";\nimport \"./interfaces/IMarketRegistry.sol\";\n\ncontract LenderManager is\n Initializable,\n OwnableUpgradeable,\n ERC721Upgradeable,\n ILenderManager\n{\n IMarketRegistry public immutable marketRegistry;\n\n constructor(IMarketRegistry _marketRegistry) {\n marketRegistry = _marketRegistry;\n }\n\n function initialize() external initializer {\n __LenderManager_init();\n }\n\n function __LenderManager_init() internal onlyInitializing {\n __Ownable_init();\n __ERC721_init(\"TellerLoan\", \"TLN\");\n }\n\n /**\n * @notice Registers a new active lender for a loan, minting the nft\n * @param _bidId The id for the loan to set.\n * @param _newLender The address of the new active lender.\n */\n function registerLoan(uint256 _bidId, address _newLender)\n public\n override\n onlyOwner\n {\n _safeMint(_newLender, _bidId, \"\");\n }\n\n /**\n * @notice Returns the address of the lender that owns a given loan/bid.\n * @param _bidId The id of the bid of which to return the market id\n */\n function _getLoanMarketId(uint256 _bidId) internal view returns (uint256) {\n return ITellerV2(owner()).getLoanMarketId(_bidId);\n }\n\n /**\n * @notice Returns the verification status of a lender for a market.\n * @param _lender The address of the lender which should be verified by the market\n * @param _bidId The id of the bid of which to return the market id\n */\n function _hasMarketVerification(address _lender, uint256 _bidId)\n internal\n view\n virtual\n returns (bool isVerified_)\n {\n uint256 _marketId = _getLoanMarketId(_bidId);\n\n (isVerified_, ) = marketRegistry.isVerifiedLender(_marketId, _lender);\n }\n\n /** ERC721 Functions **/\n\n function _beforeTokenTransfer(address, address to, uint256 tokenId, uint256)\n internal\n override\n {\n require(_hasMarketVerification(to, tokenId), \"Not approved by market\");\n }\n\n function _baseURI() internal view override returns (string memory) {\n return \"\";\n }\n}\n" + }, + "contracts/libraries/DateTimeLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\n// ----------------------------------------------------------------------------\n// BokkyPooBah's DateTime Library v1.01\n//\n// A gas-efficient Solidity date and time library\n//\n// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\n//\n// Tested date range 1970/01/01 to 2345/12/31\n//\n// Conventions:\n// Unit | Range | Notes\n// :-------- |:-------------:|:-----\n// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC\n// year | 1970 ... 2345 |\n// month | 1 ... 12 |\n// day | 1 ... 31 |\n// hour | 0 ... 23 |\n// minute | 0 ... 59 |\n// second | 0 ... 59 |\n// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday\n//\n//\n// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.\n// ----------------------------------------------------------------------------\n\nlibrary BokkyPooBahsDateTimeLibrary {\n uint constant SECONDS_PER_DAY = 24 * 60 * 60;\n uint constant SECONDS_PER_HOUR = 60 * 60;\n uint constant SECONDS_PER_MINUTE = 60;\n int constant OFFSET19700101 = 2440588;\n\n uint constant DOW_MON = 1;\n uint constant DOW_TUE = 2;\n uint constant DOW_WED = 3;\n uint constant DOW_THU = 4;\n uint constant DOW_FRI = 5;\n uint constant DOW_SAT = 6;\n uint constant DOW_SUN = 7;\n\n // ------------------------------------------------------------------------\n // Calculate the number of days from 1970/01/01 to year/month/day using\n // the date conversion algorithm from\n // https://aa.usno.navy.mil/faq/JD_formula.html\n // and subtracting the offset 2440588 so that 1970/01/01 is day 0\n //\n // days = day\n // - 32075\n // + 1461 * (year + 4800 + (month - 14) / 12) / 4\n // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12\n // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4\n // - offset\n // ------------------------------------------------------------------------\n function _daysFromDate(uint year, uint month, uint day)\n internal\n pure\n returns (uint _days)\n {\n require(year >= 1970);\n int _year = int(year);\n int _month = int(month);\n int _day = int(day);\n\n int __days = _day -\n 32075 +\n (1461 * (_year + 4800 + (_month - 14) / 12)) /\n 4 +\n (367 * (_month - 2 - ((_month - 14) / 12) * 12)) /\n 12 -\n (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /\n 4 -\n OFFSET19700101;\n\n _days = uint(__days);\n }\n\n // ------------------------------------------------------------------------\n // Calculate year/month/day from the number of days since 1970/01/01 using\n // the date conversion algorithm from\n // http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n // and adding the offset 2440588 so that 1970/01/01 is day 0\n //\n // int L = days + 68569 + offset\n // int N = 4 * L / 146097\n // L = L - (146097 * N + 3) / 4\n // year = 4000 * (L + 1) / 1461001\n // L = L - 1461 * year / 4 + 31\n // month = 80 * L / 2447\n // dd = L - 2447 * month / 80\n // L = month / 11\n // month = month + 2 - 12 * L\n // year = 100 * (N - 49) + year + L\n // ------------------------------------------------------------------------\n function _daysToDate(uint _days)\n internal\n pure\n returns (uint year, uint month, uint day)\n {\n int __days = int(_days);\n\n int L = __days + 68569 + OFFSET19700101;\n int N = (4 * L) / 146097;\n L = L - (146097 * N + 3) / 4;\n int _year = (4000 * (L + 1)) / 1461001;\n L = L - (1461 * _year) / 4 + 31;\n int _month = (80 * L) / 2447;\n int _day = L - (2447 * _month) / 80;\n L = _month / 11;\n _month = _month + 2 - 12 * L;\n _year = 100 * (N - 49) + _year + L;\n\n year = uint(_year);\n month = uint(_month);\n day = uint(_day);\n }\n\n function timestampFromDate(uint year, uint month, uint day)\n internal\n pure\n returns (uint timestamp)\n {\n timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;\n }\n\n function timestampFromDateTime(\n uint year,\n uint month,\n uint day,\n uint hour,\n uint minute,\n uint second\n ) internal pure returns (uint timestamp) {\n timestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n hour *\n SECONDS_PER_HOUR +\n minute *\n SECONDS_PER_MINUTE +\n second;\n }\n\n function timestampToDate(uint timestamp)\n internal\n pure\n returns (uint year, uint month, uint day)\n {\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n\n function timestampToDateTime(uint timestamp)\n internal\n pure\n returns (\n uint year,\n uint month,\n uint day,\n uint hour,\n uint minute,\n uint second\n )\n {\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n uint secs = timestamp % SECONDS_PER_DAY;\n hour = secs / SECONDS_PER_HOUR;\n secs = secs % SECONDS_PER_HOUR;\n minute = secs / SECONDS_PER_MINUTE;\n second = secs % SECONDS_PER_MINUTE;\n }\n\n function isValidDate(uint year, uint month, uint day)\n internal\n pure\n returns (bool valid)\n {\n if (year >= 1970 && month > 0 && month <= 12) {\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > 0 && day <= daysInMonth) {\n valid = true;\n }\n }\n }\n\n function isValidDateTime(\n uint year,\n uint month,\n uint day,\n uint hour,\n uint minute,\n uint second\n ) internal pure returns (bool valid) {\n if (isValidDate(year, month, day)) {\n if (hour < 24 && minute < 60 && second < 60) {\n valid = true;\n }\n }\n }\n\n function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {\n (uint year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);\n leapYear = _isLeapYear(year);\n }\n\n function _isLeapYear(uint year) internal pure returns (bool leapYear) {\n leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);\n }\n\n function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {\n weekDay = getDayOfWeek(timestamp) <= DOW_FRI;\n }\n\n function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {\n weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;\n }\n\n function getDaysInMonth(uint timestamp)\n internal\n pure\n returns (uint daysInMonth)\n {\n (uint year, uint month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);\n daysInMonth = _getDaysInMonth(year, month);\n }\n\n function _getDaysInMonth(uint year, uint month)\n internal\n pure\n returns (uint daysInMonth)\n {\n if (\n month == 1 ||\n month == 3 ||\n month == 5 ||\n month == 7 ||\n month == 8 ||\n month == 10 ||\n month == 12\n ) {\n daysInMonth = 31;\n } else if (month != 2) {\n daysInMonth = 30;\n } else {\n daysInMonth = _isLeapYear(year) ? 29 : 28;\n }\n }\n\n // 1 = Monday, 7 = Sunday\n function getDayOfWeek(uint timestamp)\n internal\n pure\n returns (uint dayOfWeek)\n {\n uint _days = timestamp / SECONDS_PER_DAY;\n dayOfWeek = ((_days + 3) % 7) + 1;\n }\n\n function getYear(uint timestamp) internal pure returns (uint year) {\n (year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n\n function getMonth(uint timestamp) internal pure returns (uint month) {\n (, month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n\n function getDay(uint timestamp) internal pure returns (uint day) {\n (, , day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n\n function getHour(uint timestamp) internal pure returns (uint hour) {\n uint secs = timestamp % SECONDS_PER_DAY;\n hour = secs / SECONDS_PER_HOUR;\n }\n\n function getMinute(uint timestamp) internal pure returns (uint minute) {\n uint secs = timestamp % SECONDS_PER_HOUR;\n minute = secs / SECONDS_PER_MINUTE;\n }\n\n function getSecond(uint timestamp) internal pure returns (uint second) {\n second = timestamp % SECONDS_PER_MINUTE;\n }\n\n function addYears(uint timestamp, uint _years)\n internal\n pure\n returns (uint newTimestamp)\n {\n (uint year, uint month, uint day) = _daysToDate(\n timestamp / SECONDS_PER_DAY\n );\n year += _years;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n (timestamp % SECONDS_PER_DAY);\n require(newTimestamp >= timestamp);\n }\n\n function addMonths(uint timestamp, uint _months)\n internal\n pure\n returns (uint newTimestamp)\n {\n (uint year, uint month, uint day) = _daysToDate(\n timestamp / SECONDS_PER_DAY\n );\n month += _months;\n year += (month - 1) / 12;\n month = ((month - 1) % 12) + 1;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n (timestamp % SECONDS_PER_DAY);\n require(newTimestamp >= timestamp);\n }\n\n function addDays(uint timestamp, uint _days)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp + _days * SECONDS_PER_DAY;\n require(newTimestamp >= timestamp);\n }\n\n function addHours(uint timestamp, uint _hours)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;\n require(newTimestamp >= timestamp);\n }\n\n function addMinutes(uint timestamp, uint _minutes)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;\n require(newTimestamp >= timestamp);\n }\n\n function addSeconds(uint timestamp, uint _seconds)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp + _seconds;\n require(newTimestamp >= timestamp);\n }\n\n function subYears(uint timestamp, uint _years)\n internal\n pure\n returns (uint newTimestamp)\n {\n (uint year, uint month, uint day) = _daysToDate(\n timestamp / SECONDS_PER_DAY\n );\n year -= _years;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n (timestamp % SECONDS_PER_DAY);\n require(newTimestamp <= timestamp);\n }\n\n function subMonths(uint timestamp, uint _months)\n internal\n pure\n returns (uint newTimestamp)\n {\n (uint year, uint month, uint day) = _daysToDate(\n timestamp / SECONDS_PER_DAY\n );\n uint yearMonth = year * 12 + (month - 1) - _months;\n year = yearMonth / 12;\n month = (yearMonth % 12) + 1;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n (timestamp % SECONDS_PER_DAY);\n require(newTimestamp <= timestamp);\n }\n\n function subDays(uint timestamp, uint _days)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp - _days * SECONDS_PER_DAY;\n require(newTimestamp <= timestamp);\n }\n\n function subHours(uint timestamp, uint _hours)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;\n require(newTimestamp <= timestamp);\n }\n\n function subMinutes(uint timestamp, uint _minutes)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;\n require(newTimestamp <= timestamp);\n }\n\n function subSeconds(uint timestamp, uint _seconds)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp - _seconds;\n require(newTimestamp <= timestamp);\n }\n\n function diffYears(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _years)\n {\n require(fromTimestamp <= toTimestamp);\n (uint fromYear, , ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\n (uint toYear, , ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\n _years = toYear - fromYear;\n }\n\n function diffMonths(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _months)\n {\n require(fromTimestamp <= toTimestamp);\n (uint fromYear, uint fromMonth, ) = _daysToDate(\n fromTimestamp / SECONDS_PER_DAY\n );\n (uint toYear, uint toMonth, ) = _daysToDate(\n toTimestamp / SECONDS_PER_DAY\n );\n _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;\n }\n\n function diffDays(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _days)\n {\n require(fromTimestamp <= toTimestamp);\n _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;\n }\n\n function diffHours(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _hours)\n {\n require(fromTimestamp <= toTimestamp);\n _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;\n }\n\n function diffMinutes(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _minutes)\n {\n require(fromTimestamp <= toTimestamp);\n _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;\n }\n\n function diffSeconds(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _seconds)\n {\n require(fromTimestamp <= toTimestamp);\n _seconds = toTimestamp - fromTimestamp;\n }\n}\n" + }, + "contracts/libraries/NumbersLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Libraries\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"./WadRayMath.sol\";\n\n/**\n * @dev Utility library for uint256 numbers\n *\n * @author develop@teller.finance\n */\nlibrary NumbersLib {\n using WadRayMath for uint256;\n\n /**\n * @dev It represents 100% with 2 decimal places.\n */\n uint16 internal constant PCT_100 = 10000;\n\n function percentFactor(uint256 decimals) internal pure returns (uint256) {\n return 100 * (10**decimals);\n }\n\n /**\n * @notice Returns a percentage value of a number.\n * @param self The number to get a percentage of.\n * @param percentage The percentage value to calculate with 2 decimal places (10000 = 100%).\n */\n function percent(uint256 self, uint16 percentage)\n internal\n pure\n returns (uint256)\n {\n return percent(self, percentage, 2);\n }\n\n /**\n * @notice Returns a percentage value of a number.\n * @param self The number to get a percentage of.\n * @param percentage The percentage value to calculate with.\n * @param decimals The number of decimals the percentage value is in.\n */\n function percent(uint256 self, uint256 percentage, uint256 decimals)\n internal\n pure\n returns (uint256)\n {\n return (self * percentage) / percentFactor(decimals);\n }\n\n /**\n * @notice it returns the absolute number of a specified parameter\n * @param self the number to be returned in it's absolute\n * @return the absolute number\n */\n function abs(int256 self) internal pure returns (uint256) {\n return self >= 0 ? uint256(self) : uint256(-1 * self);\n }\n\n /**\n * @notice Returns a ratio percentage of {num1} to {num2}.\n * @dev Returned value is type uint16.\n * @param num1 The number used to get the ratio for.\n * @param num2 The number used to get the ratio from.\n * @return Ratio percentage with 2 decimal places (10000 = 100%).\n */\n function ratioOf(uint256 num1, uint256 num2)\n internal\n pure\n returns (uint16)\n {\n return SafeCast.toUint16(ratioOf(num1, num2, 2));\n }\n\n /**\n * @notice Returns a ratio percentage of {num1} to {num2}.\n * @param num1 The number used to get the ratio for.\n * @param num2 The number used to get the ratio from.\n * @param decimals The number of decimals the percentage value is returned in.\n * @return Ratio percentage value.\n */\n function ratioOf(uint256 num1, uint256 num2, uint256 decimals)\n internal\n pure\n returns (uint256)\n {\n if (num2 == 0) return 0;\n return (num1 * percentFactor(decimals)) / num2;\n }\n\n /**\n * @notice Calculates the payment amount for a cycle duration.\n * The formula is calculated based on the standard Estimated Monthly Installment (https://en.wikipedia.org/wiki/Equated_monthly_installment)\n * EMI = [P x R x (1+R)^N]/[(1+R)^N-1]\n * @param principal The starting amount that is owed on the loan.\n * @param loanDuration The length of the loan.\n * @param cycleDuration The length of the loan's payment cycle.\n * @param apr The annual percentage rate of the loan.\n */\n function pmt(\n uint256 principal,\n uint32 loanDuration,\n uint32 cycleDuration,\n uint16 apr,\n uint256 daysInYear\n ) internal pure returns (uint256) {\n require(\n loanDuration >= cycleDuration,\n \"PMT: cycle duration < loan duration\"\n );\n if (apr == 0)\n return\n Math.mulDiv(\n principal,\n cycleDuration,\n loanDuration,\n Math.Rounding.Up\n );\n\n // Number of payment cycles for the duration of the loan\n uint256 n = Math.ceilDiv(loanDuration, cycleDuration);\n\n uint256 one = WadRayMath.wad();\n uint256 r = WadRayMath.pctToWad(apr).wadMul(cycleDuration).wadDiv(\n daysInYear\n );\n uint256 exp = (one + r).wadPow(n);\n uint256 numerator = principal.wadMul(r).wadMul(exp);\n uint256 denominator = exp - one;\n\n return numerator.wadDiv(denominator);\n }\n}\n" + }, + "contracts/libraries/uniswap/FixedPoint96.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.4.0;\n\n/// @title FixedPoint96\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\n/// @dev Used in SqrtPriceMath.sol\nlibrary FixedPoint96 {\n uint8 internal constant RESOLUTION = 96;\n uint256 internal constant Q96 = 0x1000000000000000000000000;\n}\n" + }, + "contracts/libraries/uniswap/FullMath.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Contains 512-bit math functions\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\n/// @dev Handles \"phantom overflow\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\nlibrary FullMath {\n /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n /// @param a The multiplicand\n /// @param b The multiplier\n /// @param denominator The divisor\n /// @return result The 256-bit result\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\n function mulDiv(uint256 a, uint256 b, uint256 denominator)\n internal\n pure\n returns (uint256 result)\n {\n // 512-bit multiply [prod1 prod0] = a * b\n // Compute the product mod 2**256 and mod 2**256 - 1\n // then use the Chinese Remainder Theorem to reconstruct\n // 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(a, b, not(0))\n prod0 := mul(a, b)\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 require(denominator > 0);\n assembly {\n result := div(prod0, denominator)\n }\n return result;\n }\n\n // Make sure the result is less than 2**256.\n // Also prevents denominator == 0\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0]\n // Compute remainder using mulmod\n uint256 remainder;\n assembly {\n remainder := mulmod(a, b, denominator)\n }\n // Subtract 256 bit number from 512 bit number\n assembly {\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator\n // Compute largest power of two divisor of denominator.\n // Always >= 1.\n // uint256 twos = -denominator & denominator;\n uint256 twos = (~denominator + 1) & denominator;\n // Divide denominator by power of two\n assembly {\n denominator := div(denominator, twos)\n }\n\n // Divide [prod1 prod0] by the factors of two\n assembly {\n prod0 := div(prod0, twos)\n }\n // Shift in bits from prod1 into prod0. For this we need\n // to flip `twos` such that it is 2**256 / twos.\n // If twos is zero, then it becomes one\n assembly {\n twos := add(div(sub(0, twos), twos), 1)\n }\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2**256\n // Now that denominator is an odd number, it has an inverse\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\n // Compute the inverse by starting with a seed that is correct\n // correct for four bits. That is, denominator * inv = 1 mod 2**4\n uint256 inv = (3 * denominator) ^ 2;\n // Now use Newton-Raphson iteration to improve the precision.\n // Thanks to Hensel's lifting lemma, this also works in modular\n // arithmetic, doubling the correct bits in each step.\n inv *= 2 - denominator * inv; // inverse mod 2**8\n inv *= 2 - denominator * inv; // inverse mod 2**16\n inv *= 2 - denominator * inv; // inverse mod 2**32\n inv *= 2 - denominator * inv; // inverse mod 2**64\n inv *= 2 - denominator * inv; // inverse mod 2**128\n inv *= 2 - denominator * inv; // inverse mod 2**256\n\n // Because the division is now exact we can divide by multiplying\n // with the modular inverse of denominator. This will give us the\n // correct result modulo 2**256. Since the precoditions guarantee\n // that the outcome is less than 2**256, this is the final result.\n // We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inv;\n return result;\n }\n\n /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n /// @param a The multiplicand\n /// @param b The multiplier\n /// @param denominator The divisor\n /// @return result The 256-bit result\n function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator)\n internal\n pure\n returns (uint256 result)\n {\n result = mulDiv(a, b, denominator);\n if (mulmod(a, b, denominator) > 0) {\n require(result < type(uint256).max);\n result++;\n }\n }\n}\n" + }, + "contracts/libraries/uniswap/TickMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\n/// @title Math library for computing sqrt prices from ticks and vice versa\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\n/// prices between 2**-128 and 2**128\nlibrary TickMath {\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\n int24 internal constant MIN_TICK = -887272;\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\n int24 internal constant MAX_TICK = -MIN_TICK;\n\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\n uint160 internal constant MAX_SQRT_RATIO =\n 1461446703485210103287273052203988822378723970342;\n\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\n /// @dev Throws if |tick| > max tick\n /// @param tick The input tick for the above formula\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\n /// at the given tick\n function getSqrtRatioAtTick(int24 tick)\n internal\n pure\n returns (uint160 sqrtPriceX96)\n {\n uint256 absTick = tick < 0\n ? uint256(-int256(tick))\n : uint256(int256(tick));\n require(absTick <= uint256(uint24(MAX_TICK)), \"T\");\n\n uint256 ratio = absTick & 0x1 != 0\n ? 0xfffcb933bd6fad37aa2d162d1a594001\n : 0x100000000000000000000000000000000;\n if (absTick & 0x2 != 0)\n ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\n if (absTick & 0x4 != 0)\n ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\n if (absTick & 0x8 != 0)\n ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\n if (absTick & 0x10 != 0)\n ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\n if (absTick & 0x20 != 0)\n ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\n if (absTick & 0x40 != 0)\n ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\n if (absTick & 0x80 != 0)\n ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\n if (absTick & 0x100 != 0)\n ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\n if (absTick & 0x200 != 0)\n ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\n if (absTick & 0x400 != 0)\n ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\n if (absTick & 0x800 != 0)\n ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\n if (absTick & 0x1000 != 0)\n ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\n if (absTick & 0x2000 != 0)\n ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\n if (absTick & 0x4000 != 0)\n ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\n if (absTick & 0x8000 != 0)\n ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\n if (absTick & 0x10000 != 0)\n ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\n if (absTick & 0x20000 != 0)\n ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\n if (absTick & 0x40000 != 0)\n ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\n if (absTick & 0x80000 != 0)\n ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\n\n if (tick > 0) ratio = type(uint256).max / ratio;\n\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\n sqrtPriceX96 = uint160(\n (ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)\n );\n }\n\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\n /// ever return.\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\n function getTickAtSqrtRatio(uint160 sqrtPriceX96)\n internal\n pure\n returns (int24 tick)\n {\n // second inequality must be < because the price can never reach the price at the max tick\n require(\n sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO,\n \"R\"\n );\n uint256 ratio = uint256(sqrtPriceX96) << 32;\n\n uint256 r = ratio;\n uint256 msb = 0;\n\n assembly {\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(5, gt(r, 0xFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(4, gt(r, 0xFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(3, gt(r, 0xFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(2, gt(r, 0xF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(1, gt(r, 0x3))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := gt(r, 0x1)\n msb := or(msb, f)\n }\n\n if (msb >= 128) r = ratio >> (msb - 127);\n else r = ratio << (127 - msb);\n\n int256 log_2 = (int256(msb) - 128) << 64;\n\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(63, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(62, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(61, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(60, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(59, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(58, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(57, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(56, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(55, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(54, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(53, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(52, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(51, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(50, f))\n }\n\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\n\n int24 tickLow = int24(\n (log_sqrt10001 - 3402992956809132418596140100660247210) >> 128\n );\n int24 tickHi = int24(\n (log_sqrt10001 + 291339464771989622907027621153398088495) >> 128\n );\n\n tick = tickLow == tickHi\n ? tickLow\n : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96\n ? tickHi\n : tickLow;\n }\n}\n" + }, + "contracts/libraries/UniswapPricingLibrary.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n \n\nimport {IUniswapPricingLibrary} from \"../interfaces/IUniswapPricingLibrary.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\n\n \nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\n\nimport \"../interfaces/uniswap/IUniswapV3Pool.sol\"; \n\nimport \"../libraries/uniswap/TickMath.sol\";\nimport \"../libraries/uniswap/FixedPoint96.sol\";\nimport \"../libraries/uniswap/FullMath.sol\";\n \n \nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n\n/*\n\nOnly do decimal expansion if it is an ERC20 not anything else !! \n\n*/\n\nlibrary UniswapPricingLibrary \n{\n \n uint256 constant STANDARD_EXPANSION_FACTOR = 1e18;\n\n function getUniswapPriceRatioForPoolRoutes(\n IUniswapPricingLibrary.PoolRouteConfig[] memory poolRoutes\n ) public view returns (uint256 priceRatio) {\n require(poolRoutes.length <= 2, \"invalid pool routes length\");\n\n if (poolRoutes.length == 2) {\n uint256 pool0PriceRatio = getUniswapPriceRatioForPool(\n poolRoutes[0]\n );\n\n uint256 pool1PriceRatio = getUniswapPriceRatioForPool(\n poolRoutes[1]\n );\n\n return\n FullMath.mulDiv(\n pool0PriceRatio,\n pool1PriceRatio,\n STANDARD_EXPANSION_FACTOR\n );\n } else if (poolRoutes.length == 1) {\n return getUniswapPriceRatioForPool(poolRoutes[0]);\n }\n\n //else return 0\n }\n\n /*\n The resultant product is expanded by STANDARD_EXPANSION_FACTOR one time \n */\n function getUniswapPriceRatioForPool(\n IUniswapPricingLibrary.PoolRouteConfig memory _poolRouteConfig\n ) public view returns (uint256 priceRatio) {\n uint160 sqrtPriceX96 = getSqrtTwapX96(\n _poolRouteConfig.pool,\n _poolRouteConfig.twapInterval\n );\n\n //This is the token 1 per token 0 price\n uint256 sqrtPrice = FullMath.mulDiv(\n sqrtPriceX96,\n STANDARD_EXPANSION_FACTOR,\n 2**96\n );\n\n uint256 sqrtPriceInverse = (STANDARD_EXPANSION_FACTOR *\n STANDARD_EXPANSION_FACTOR) / sqrtPrice;\n\n uint256 price = _poolRouteConfig.zeroForOne\n ? sqrtPrice * sqrtPrice\n : sqrtPriceInverse * sqrtPriceInverse;\n\n return price / STANDARD_EXPANSION_FACTOR;\n }\n\n\n\n function getSqrtTwapX96(address uniswapV3Pool, uint32 twapInterval)\n internal\n view\n returns (uint160 sqrtPriceX96)\n {\n if (twapInterval == 0) {\n // return the current price if twapInterval == 0\n (sqrtPriceX96, , , , , , ) = IUniswapV3Pool(uniswapV3Pool).slot0();\n } else {\n uint32[] memory secondsAgos = new uint32[](2);\n secondsAgos[0] = twapInterval + 1; // from (before)\n secondsAgos[1] = 1; // one block prior\n\n (int56[] memory tickCumulatives, ) = IUniswapV3Pool(uniswapV3Pool)\n .observe(secondsAgos);\n\n // tick(imprecise as it's an integer) to price\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(\n int24(\n (tickCumulatives[1] - tickCumulatives[0]) /\n int32(twapInterval)\n )\n );\n }\n }\n\n function getPriceX96FromSqrtPriceX96(uint160 sqrtPriceX96)\n internal\n pure\n returns (uint256 priceX96)\n { \n\n \n return FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96);\n }\n\n}" + }, + "contracts/libraries/V2Calculations.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n\n// SPDX-License-Identifier: MIT\n\n// Libraries\nimport \"./NumbersLib.sol\";\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Bid } from \"../TellerV2Storage.sol\";\nimport { BokkyPooBahsDateTimeLibrary as BPBDTL } from \"./DateTimeLib.sol\";\n\nenum PaymentType {\n EMI,\n Bullet\n}\n\nenum PaymentCycleType {\n Seconds,\n Monthly\n}\n\nlibrary V2Calculations {\n using NumbersLib for uint256;\n\n /**\n * @notice Returns the timestamp of the last payment made for a loan.\n * @param _bid The loan bid struct to get the timestamp for.\n */\n function lastRepaidTimestamp(Bid storage _bid)\n internal\n view\n returns (uint32)\n {\n return\n _bid.loanDetails.lastRepaidTimestamp == 0\n ? _bid.loanDetails.acceptedTimestamp\n : _bid.loanDetails.lastRepaidTimestamp;\n }\n\n /**\n * @notice Calculates the amount owed for a loan.\n * @param _bid The loan bid struct to get the owed amount for.\n * @param _timestamp The timestamp at which to get the owed amount at.\n * @param _paymentCycleType The payment cycle type of the loan (Seconds or Monthly).\n */\n function calculateAmountOwed(\n Bid storage _bid,\n uint256 _timestamp,\n PaymentCycleType _paymentCycleType,\n uint32 _paymentCycleDuration\n )\n public\n view\n returns (\n uint256 owedPrincipal_,\n uint256 duePrincipal_,\n uint256 interest_\n )\n {\n // Total principal left to pay\n return\n calculateAmountOwed(\n _bid,\n lastRepaidTimestamp(_bid),\n _timestamp,\n _paymentCycleType,\n _paymentCycleDuration\n );\n }\n\n function calculateAmountOwed(\n Bid storage _bid,\n uint256 _lastRepaidTimestamp,\n uint256 _timestamp,\n PaymentCycleType _paymentCycleType,\n uint32 _paymentCycleDuration\n )\n public\n view\n returns (\n uint256 owedPrincipal_,\n uint256 duePrincipal_,\n uint256 interest_\n )\n {\n owedPrincipal_ =\n _bid.loanDetails.principal -\n _bid.loanDetails.totalRepaid.principal;\n\n uint256 owedTime = _timestamp - uint256(_lastRepaidTimestamp);\n\n {\n uint256 daysInYear = _paymentCycleType == PaymentCycleType.Monthly\n ? 360 days\n : 365 days;\n\n uint256 interestOwedInAYear = owedPrincipal_.percent(_bid.terms.APR, 2);\n \n interest_ = (interestOwedInAYear * owedTime) / daysInYear;\n }\n\n\n bool isLastPaymentCycle;\n {\n uint256 lastPaymentCycleDuration = _bid.loanDetails.loanDuration %\n _paymentCycleDuration;\n if (lastPaymentCycleDuration == 0) {\n lastPaymentCycleDuration = _paymentCycleDuration;\n }\n\n uint256 endDate = uint256(_bid.loanDetails.acceptedTimestamp) +\n uint256(_bid.loanDetails.loanDuration);\n uint256 lastPaymentCycleStart = endDate -\n uint256(lastPaymentCycleDuration);\n\n isLastPaymentCycle =\n uint256(_timestamp) > lastPaymentCycleStart ||\n owedPrincipal_ + interest_ <= _bid.terms.paymentCycleAmount;\n }\n\n if (_bid.paymentType == PaymentType.Bullet) {\n if (isLastPaymentCycle) {\n duePrincipal_ = owedPrincipal_;\n }\n } else {\n // Default to PaymentType.EMI\n // Max payable amount in a cycle\n // NOTE: the last cycle could have less than the calculated payment amount\n\n //the amount owed for the cycle should never exceed the current payment cycle amount so we use min here \n uint256 owedAmountForCycle = Math.min( ((_bid.terms.paymentCycleAmount * owedTime) ) /\n _paymentCycleDuration , _bid.terms.paymentCycleAmount+interest_ ) ;\n\n uint256 owedAmount = isLastPaymentCycle\n ? owedPrincipal_ + interest_\n : owedAmountForCycle ;\n\n duePrincipal_ = Math.min(owedAmount - interest_, owedPrincipal_);\n }\n }\n\n /**\n * @notice Calculates the amount owed for a loan for the next payment cycle.\n * @param _type The payment type of the loan.\n * @param _cycleType The cycle type set for the loan. (Seconds or Monthly)\n * @param _principal The starting amount that is owed on the loan.\n * @param _duration The length of the loan.\n * @param _paymentCycle The length of the loan's payment cycle.\n * @param _apr The annual percentage rate of the loan.\n */\n function calculatePaymentCycleAmount(\n PaymentType _type,\n PaymentCycleType _cycleType,\n uint256 _principal,\n uint32 _duration,\n uint32 _paymentCycle,\n uint16 _apr\n ) public view returns (uint256) {\n uint256 daysInYear = _cycleType == PaymentCycleType.Monthly\n ? 360 days\n : 365 days;\n if (_type == PaymentType.Bullet) {\n return\n _principal.percent(_apr).percent(\n uint256(_paymentCycle).ratioOf(daysInYear, 10),\n 10\n );\n }\n // Default to PaymentType.EMI\n return\n NumbersLib.pmt(\n _principal,\n _duration,\n _paymentCycle,\n _apr,\n daysInYear\n );\n }\n\n function calculateNextDueDate(\n uint32 _acceptedTimestamp,\n uint32 _paymentCycle,\n uint32 _loanDuration,\n uint32 _lastRepaidTimestamp,\n PaymentCycleType _bidPaymentCycleType\n ) public view returns (uint32 dueDate_) {\n // Calculate due date if payment cycle is set to monthly\n if (_bidPaymentCycleType == PaymentCycleType.Monthly) {\n // Calculate the cycle number the last repayment was made\n uint256 lastPaymentCycle = BPBDTL.diffMonths(\n _acceptedTimestamp,\n _lastRepaidTimestamp\n );\n if (\n BPBDTL.getDay(_lastRepaidTimestamp) >\n BPBDTL.getDay(_acceptedTimestamp)\n ) {\n lastPaymentCycle += 2;\n } else {\n lastPaymentCycle += 1;\n }\n\n dueDate_ = uint32(\n BPBDTL.addMonths(_acceptedTimestamp, lastPaymentCycle)\n );\n } else if (_bidPaymentCycleType == PaymentCycleType.Seconds) {\n // Start with the original due date being 1 payment cycle since bid was accepted\n dueDate_ = _acceptedTimestamp + _paymentCycle;\n // Calculate the cycle number the last repayment was made\n uint32 delta = _lastRepaidTimestamp - _acceptedTimestamp;\n if (delta > 0) {\n uint32 repaymentCycle = uint32(\n Math.ceilDiv(delta, _paymentCycle)\n );\n dueDate_ += (repaymentCycle * _paymentCycle);\n }\n }\n\n uint32 endOfLoan = _acceptedTimestamp + _loanDuration;\n //if we are in the last payment cycle, the next due date is the end of loan duration\n if (dueDate_ > endOfLoan) {\n dueDate_ = endOfLoan;\n }\n }\n}\n" + }, + "contracts/libraries/WadRayMath.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title WadRayMath library\n * @author Multiplier Finance\n * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits)\n */\nlibrary WadRayMath {\n using SafeMath for uint256;\n\n uint256 internal constant WAD = 1e18;\n uint256 internal constant halfWAD = WAD / 2;\n\n uint256 internal constant RAY = 1e27;\n uint256 internal constant halfRAY = RAY / 2;\n\n uint256 internal constant WAD_RAY_RATIO = 1e9;\n uint256 internal constant PCT_WAD_RATIO = 1e14;\n uint256 internal constant PCT_RAY_RATIO = 1e23;\n\n function ray() internal pure returns (uint256) {\n return RAY;\n }\n\n function wad() internal pure returns (uint256) {\n return WAD;\n }\n\n function halfRay() internal pure returns (uint256) {\n return halfRAY;\n }\n\n function halfWad() internal pure returns (uint256) {\n return halfWAD;\n }\n\n function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {\n return halfWAD.add(a.mul(b)).div(WAD);\n }\n\n function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 halfB = b / 2;\n\n return halfB.add(a.mul(WAD)).div(b);\n }\n\n function rayMul(uint256 a, uint256 b) internal pure returns (uint256) {\n return halfRAY.add(a.mul(b)).div(RAY);\n }\n\n function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 halfB = b / 2;\n\n return halfB.add(a.mul(RAY)).div(b);\n }\n\n function rayToWad(uint256 a) internal pure returns (uint256) {\n uint256 halfRatio = WAD_RAY_RATIO / 2;\n\n return halfRatio.add(a).div(WAD_RAY_RATIO);\n }\n\n function rayToPct(uint256 a) internal pure returns (uint16) {\n uint256 halfRatio = PCT_RAY_RATIO / 2;\n\n uint256 val = halfRatio.add(a).div(PCT_RAY_RATIO);\n return SafeCast.toUint16(val);\n }\n\n function wadToPct(uint256 a) internal pure returns (uint16) {\n uint256 halfRatio = PCT_WAD_RATIO / 2;\n\n uint256 val = halfRatio.add(a).div(PCT_WAD_RATIO);\n return SafeCast.toUint16(val);\n }\n\n function wadToRay(uint256 a) internal pure returns (uint256) {\n return a.mul(WAD_RAY_RATIO);\n }\n\n function pctToRay(uint16 a) internal pure returns (uint256) {\n return uint256(a).mul(RAY).div(1e4);\n }\n\n function pctToWad(uint16 a) internal pure returns (uint256) {\n return uint256(a).mul(WAD).div(1e4);\n }\n\n /**\n * @dev calculates base^duration. The code uses the ModExp precompile\n * @return z base^duration, in ray\n */\n function rayPow(uint256 x, uint256 n) internal pure returns (uint256) {\n return _pow(x, n, RAY, rayMul);\n }\n\n function wadPow(uint256 x, uint256 n) internal pure returns (uint256) {\n return _pow(x, n, WAD, wadMul);\n }\n\n function _pow(\n uint256 x,\n uint256 n,\n uint256 p,\n function(uint256, uint256) internal pure returns (uint256) mul\n ) internal pure returns (uint256 z) {\n z = n % 2 != 0 ? x : p;\n\n for (n /= 2; n != 0; n /= 2) {\n x = mul(x, x);\n\n if (n % 2 != 0) {\n z = mul(z, x);\n }\n }\n }\n}\n" + }, + "contracts/MarketLiquidityRewards.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"./interfaces/IMarketLiquidityRewards.sol\";\n\nimport \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/ICollateralManager.sol\";\nimport \"./interfaces/ITellerV2.sol\";\n\nimport { BidState } from \"./TellerV2Storage.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/*\n- Allocate and claim rewards for loans based on bidId \n\n- Anyone can allocate rewards and an allocation has specific parameters that can be set to incentivise certain types of loans\n \n*/\n\ncontract MarketLiquidityRewards is IMarketLiquidityRewards, Initializable {\n address immutable tellerV2;\n address immutable marketRegistry;\n address immutable collateralManager;\n\n uint256 allocationCount;\n\n //allocationId => rewardAllocation\n mapping(uint256 => RewardAllocation) public allocatedRewards;\n\n //bidId => allocationId => rewardWasClaimed\n mapping(uint256 => mapping(uint256 => bool)) public rewardClaimedForBid;\n\n modifier onlyMarketOwner(uint256 _marketId) {\n require(\n msg.sender ==\n IMarketRegistry(marketRegistry).getMarketOwner(_marketId),\n \"Only market owner can call this function.\"\n );\n _;\n }\n\n event CreatedAllocation(\n uint256 allocationId,\n address allocator,\n uint256 marketId\n );\n\n event UpdatedAllocation(uint256 allocationId);\n\n event IncreasedAllocation(uint256 allocationId, uint256 amount);\n\n event DecreasedAllocation(uint256 allocationId, uint256 amount);\n\n event DeletedAllocation(uint256 allocationId);\n\n event ClaimedRewards(\n uint256 allocationId,\n uint256 bidId,\n address recipient,\n uint256 amount\n );\n\n constructor(\n address _tellerV2,\n address _marketRegistry,\n address _collateralManager\n ) {\n tellerV2 = _tellerV2;\n marketRegistry = _marketRegistry;\n collateralManager = _collateralManager;\n }\n\n function initialize() external initializer {}\n\n /**\n * @notice Creates a new token allocation and transfers the token amount into escrow in this contract\n * @param _allocation - The RewardAllocation struct data to create\n * @return allocationId_\n */\n function allocateRewards(RewardAllocation calldata _allocation)\n public\n virtual\n returns (uint256 allocationId_)\n {\n allocationId_ = allocationCount++;\n\n require(\n _allocation.allocator == msg.sender,\n \"Invalid allocator address\"\n );\n\n require(\n _allocation.requiredPrincipalTokenAddress != address(0),\n \"Invalid required principal token address\"\n );\n\n IERC20Upgradeable(_allocation.rewardTokenAddress).transferFrom(\n msg.sender,\n address(this),\n _allocation.rewardTokenAmount\n );\n\n allocatedRewards[allocationId_] = _allocation;\n\n emit CreatedAllocation(\n allocationId_,\n _allocation.allocator,\n _allocation.marketId\n );\n }\n\n /**\n * @notice Allows the allocator to update properties of an allocation\n * @param _allocationId - The id for the allocation\n * @param _minimumCollateralPerPrincipalAmount - The required collateralization ratio\n * @param _rewardPerLoanPrincipalAmount - The reward to give per principal amount\n * @param _bidStartTimeMin - The block timestamp that loans must have been accepted after to claim rewards\n * @param _bidStartTimeMax - The block timestamp that loans must have been accepted before to claim rewards\n */\n function updateAllocation(\n uint256 _allocationId,\n uint256 _minimumCollateralPerPrincipalAmount,\n uint256 _rewardPerLoanPrincipalAmount,\n uint32 _bidStartTimeMin,\n uint32 _bidStartTimeMax\n ) public virtual {\n RewardAllocation storage allocation = allocatedRewards[_allocationId];\n\n require(\n msg.sender == allocation.allocator,\n \"Only the allocator can update allocation rewards.\"\n );\n\n allocation\n .minimumCollateralPerPrincipalAmount = _minimumCollateralPerPrincipalAmount;\n allocation.rewardPerLoanPrincipalAmount = _rewardPerLoanPrincipalAmount;\n allocation.bidStartTimeMin = _bidStartTimeMin;\n allocation.bidStartTimeMax = _bidStartTimeMax;\n\n emit UpdatedAllocation(_allocationId);\n }\n\n /**\n * @notice Allows anyone to add tokens to an allocation\n * @param _allocationId - The id for the allocation\n * @param _tokenAmount - The amount of tokens to add\n */\n function increaseAllocationAmount(\n uint256 _allocationId,\n uint256 _tokenAmount\n ) public virtual {\n IERC20Upgradeable(allocatedRewards[_allocationId].rewardTokenAddress)\n .transferFrom(msg.sender, address(this), _tokenAmount);\n allocatedRewards[_allocationId].rewardTokenAmount += _tokenAmount;\n\n emit IncreasedAllocation(_allocationId, _tokenAmount);\n }\n\n /**\n * @notice Allows the allocator to withdraw some or all of the funds within an allocation\n * @param _allocationId - The id for the allocation\n * @param _tokenAmount - The amount of tokens to withdraw\n */\n function deallocateRewards(uint256 _allocationId, uint256 _tokenAmount)\n public\n virtual\n {\n require(\n msg.sender == allocatedRewards[_allocationId].allocator,\n \"Only the allocator can deallocate rewards.\"\n );\n\n //enforce that the token amount withdraw must be LEQ to the reward amount for this allocation\n if (_tokenAmount > allocatedRewards[_allocationId].rewardTokenAmount) {\n _tokenAmount = allocatedRewards[_allocationId].rewardTokenAmount;\n }\n\n //subtract amount reward before transfer\n _decrementAllocatedAmount(_allocationId, _tokenAmount);\n\n IERC20Upgradeable(allocatedRewards[_allocationId].rewardTokenAddress)\n .transfer(msg.sender, _tokenAmount);\n\n //if the allocated rewards are drained completely, delete the storage slot for it\n if (allocatedRewards[_allocationId].rewardTokenAmount == 0) {\n delete allocatedRewards[_allocationId];\n\n emit DeletedAllocation(_allocationId);\n } else {\n emit DecreasedAllocation(_allocationId, _tokenAmount);\n }\n }\n\n struct LoanSummary {\n address borrower;\n address lender;\n uint256 marketId;\n address principalTokenAddress;\n uint256 principalAmount;\n uint32 acceptedTimestamp;\n uint32 lastRepaidTimestamp;\n BidState bidState;\n }\n\n function _getLoanSummary(uint256 _bidId)\n internal\n returns (LoanSummary memory _summary)\n {\n (\n _summary.borrower,\n _summary.lender,\n _summary.marketId,\n _summary.principalTokenAddress,\n _summary.principalAmount,\n _summary.acceptedTimestamp,\n _summary.lastRepaidTimestamp,\n _summary.bidState\n ) = ITellerV2(tellerV2).getLoanSummary(_bidId);\n }\n\n /**\n * @notice Allows a borrower or lender to withdraw the allocated ERC20 reward for their loan\n * @param _allocationId - The id for the reward allocation\n * @param _bidId - The id for the loan. Each loan only grants one reward per allocation.\n */\n function claimRewards(uint256 _allocationId, uint256 _bidId)\n external\n virtual\n {\n RewardAllocation storage allocatedReward = allocatedRewards[\n _allocationId\n ];\n\n //set a flag that this reward was claimed for this bid to defend against re-entrancy\n require(\n !rewardClaimedForBid[_bidId][_allocationId],\n \"reward already claimed\"\n );\n rewardClaimedForBid[_bidId][_allocationId] = true;\n\n //make this a struct ?\n LoanSummary memory loanSummary = _getLoanSummary(_bidId); //ITellerV2(tellerV2).getLoanSummary(_bidId);\n\n address collateralTokenAddress = allocatedReward\n .requiredCollateralTokenAddress;\n\n //require that the loan was started in the correct timeframe\n _verifyLoanStartTime(\n loanSummary.acceptedTimestamp,\n allocatedReward.bidStartTimeMin,\n allocatedReward.bidStartTimeMax\n );\n\n //if a collateral token address is set on the allocation, verify that the bid has enough collateral ratio\n if (collateralTokenAddress != address(0)) {\n uint256 collateralAmount = ICollateralManager(collateralManager)\n .getCollateralAmount(_bidId, collateralTokenAddress);\n\n //require collateral amount\n _verifyCollateralAmount(\n collateralTokenAddress,\n collateralAmount,\n loanSummary.principalTokenAddress,\n loanSummary.principalAmount,\n allocatedReward.minimumCollateralPerPrincipalAmount\n );\n }\n\n require(\n loanSummary.principalTokenAddress ==\n allocatedReward.requiredPrincipalTokenAddress,\n \"Principal token address mismatch for allocation\"\n );\n\n require(\n loanSummary.marketId == allocatedRewards[_allocationId].marketId,\n \"MarketId mismatch for allocation\"\n );\n\n uint256 principalTokenDecimals = IERC20MetadataUpgradeable(\n loanSummary.principalTokenAddress\n ).decimals();\n\n address rewardRecipient = _verifyAndReturnRewardRecipient(\n allocatedReward.allocationStrategy,\n loanSummary.bidState,\n loanSummary.borrower,\n loanSummary.lender\n );\n\n uint32 loanDuration = loanSummary.lastRepaidTimestamp -\n loanSummary.acceptedTimestamp;\n\n uint256 amountToReward = _calculateRewardAmount(\n loanSummary.principalAmount,\n loanDuration,\n principalTokenDecimals,\n allocatedReward.rewardPerLoanPrincipalAmount\n );\n\n if (amountToReward > allocatedReward.rewardTokenAmount) {\n amountToReward = allocatedReward.rewardTokenAmount;\n }\n\n require(amountToReward > 0, \"Nothing to claim.\");\n\n _decrementAllocatedAmount(_allocationId, amountToReward);\n\n //transfer tokens reward to the msgsender\n IERC20Upgradeable(allocatedRewards[_allocationId].rewardTokenAddress)\n .transfer(rewardRecipient, amountToReward);\n\n emit ClaimedRewards(\n _allocationId,\n _bidId,\n rewardRecipient,\n amountToReward\n );\n }\n\n /**\n * @notice Verifies that the bid state is appropriate for claiming rewards based on the allocation strategy and then returns the address of the reward recipient(borrower or lender)\n * @param _strategy - The strategy for the reward allocation.\n * @param _bidState - The bid state of the loan.\n * @param _borrower - The borrower of the loan.\n * @param _lender - The lender of the loan.\n * @return rewardRecipient_ The address that will receive the rewards. Either the borrower or lender.\n */\n function _verifyAndReturnRewardRecipient(\n AllocationStrategy _strategy,\n BidState _bidState,\n address _borrower,\n address _lender\n ) internal virtual returns (address rewardRecipient_) {\n if (_strategy == AllocationStrategy.BORROWER) {\n require(_bidState == BidState.PAID, \"Invalid bid state for loan.\");\n\n rewardRecipient_ = _borrower;\n } else if (_strategy == AllocationStrategy.LENDER) {\n //Loan must have been accepted in the past\n require(\n _bidState >= BidState.ACCEPTED,\n \"Invalid bid state for loan.\"\n );\n\n rewardRecipient_ = _lender;\n } else {\n revert(\"Unknown allocation strategy\");\n }\n }\n\n /**\n * @notice Decrements the amount allocated to keep track of tokens in escrow\n * @param _allocationId - The id for the allocation to decrement\n * @param _amount - The amount of ERC20 to decrement\n */\n function _decrementAllocatedAmount(uint256 _allocationId, uint256 _amount)\n internal\n {\n allocatedRewards[_allocationId].rewardTokenAmount -= _amount;\n }\n\n /**\n * @notice Calculates the reward to claim for the allocation\n * @param _loanPrincipal - The amount of principal for the loan for which to reward\n * @param _loanDuration - The duration of the loan in seconds\n * @param _principalTokenDecimals - The number of decimals of the principal token\n * @param _rewardPerLoanPrincipalAmount - The amount of reward per loan principal amount, expanded by the principal token decimals\n * @return The amount of ERC20 to reward\n */\n function _calculateRewardAmount(\n uint256 _loanPrincipal,\n uint256 _loanDuration,\n uint256 _principalTokenDecimals,\n uint256 _rewardPerLoanPrincipalAmount\n ) internal view returns (uint256) {\n uint256 rewardPerYear = MathUpgradeable.mulDiv(\n _loanPrincipal,\n _rewardPerLoanPrincipalAmount, //expanded by principal token decimals\n 10**_principalTokenDecimals\n );\n\n return MathUpgradeable.mulDiv(rewardPerYear, _loanDuration, 365 days);\n }\n\n /**\n * @notice Verifies that the collateral ratio for the loan was sufficient based on _minimumCollateralPerPrincipalAmount of the allocation\n * @param _collateralTokenAddress - The contract address for the collateral token\n * @param _collateralAmount - The number of decimals of the collateral token\n * @param _principalTokenAddress - The contract address for the principal token\n * @param _principalAmount - The number of decimals of the principal token\n * @param _minimumCollateralPerPrincipalAmount - The amount of collateral required per principal amount. Expanded by the principal token decimals and collateral token decimals.\n */\n function _verifyCollateralAmount(\n address _collateralTokenAddress,\n uint256 _collateralAmount,\n address _principalTokenAddress,\n uint256 _principalAmount,\n uint256 _minimumCollateralPerPrincipalAmount\n ) internal virtual {\n uint256 principalTokenDecimals = IERC20MetadataUpgradeable(\n _principalTokenAddress\n ).decimals();\n\n uint256 collateralTokenDecimals = IERC20MetadataUpgradeable(\n _collateralTokenAddress\n ).decimals();\n\n uint256 minCollateral = _requiredCollateralAmount(\n _principalAmount,\n principalTokenDecimals,\n collateralTokenDecimals,\n _minimumCollateralPerPrincipalAmount\n );\n\n require(\n _collateralAmount >= minCollateral,\n \"Loan does not meet minimum collateralization ratio.\"\n );\n }\n\n /**\n * @notice Calculates the minimum amount of collateral the loan requires based on principal amount\n * @param _principalAmount - The number of decimals of the principal token\n * @param _principalTokenDecimals - The number of decimals of the principal token\n * @param _collateralTokenDecimals - The number of decimals of the collateral token\n * @param _minimumCollateralPerPrincipalAmount - The amount of collateral required per principal amount. Expanded by the principal token decimals and collateral token decimals.\n */\n function _requiredCollateralAmount(\n uint256 _principalAmount,\n uint256 _principalTokenDecimals,\n uint256 _collateralTokenDecimals,\n uint256 _minimumCollateralPerPrincipalAmount\n ) internal view virtual returns (uint256) {\n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n _minimumCollateralPerPrincipalAmount, //expanded by principal token decimals and collateral token decimals\n 10**(_principalTokenDecimals + _collateralTokenDecimals)\n );\n }\n\n /**\n * @notice Verifies that the loan start time is within the bounds set by the allocation requirements\n * @param _loanStartTime - The timestamp when the loan was accepted\n * @param _minStartTime - The minimum time required, after which the loan must have been accepted\n * @param _maxStartTime - The maximum time required, before which the loan must have been accepted\n */\n function _verifyLoanStartTime(\n uint32 _loanStartTime,\n uint32 _minStartTime,\n uint32 _maxStartTime\n ) internal virtual {\n require(\n _minStartTime == 0 || _loanStartTime > _minStartTime,\n \"Loan was accepted before the min start time.\"\n );\n require(\n _maxStartTime == 0 || _loanStartTime < _maxStartTime,\n \"Loan was accepted after the max start time.\"\n );\n }\n\n /**\n * @notice Returns the amount of reward tokens remaining in the allocation\n * @param _allocationId - The id for the allocation\n */\n function getRewardTokenAmount(uint256 _allocationId)\n public\n view\n override\n returns (uint256)\n {\n return allocatedRewards[_allocationId].rewardTokenAmount;\n }\n}\n" + }, + "contracts/MarketRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"./EAS/TellerAS.sol\";\nimport \"./EAS/TellerASResolver.sol\";\n\n//must continue to use this so storage slots are not broken\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts/utils/Context.sol\";\n\n// Interfaces\nimport \"./interfaces/IMarketRegistry.sol\";\n\n// Libraries\nimport { EnumerableSet } from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport { PaymentType } from \"./libraries/V2Calculations.sol\";\n\ncontract MarketRegistry is\n IMarketRegistry,\n Initializable,\n Context,\n TellerASResolver\n{\n using EnumerableSet for EnumerableSet.AddressSet;\n\n /** Constant Variables **/\n\n uint256 public constant CURRENT_CODE_VERSION = 8;\n\n /* Storage Variables */\n\n struct Marketplace {\n address owner;\n string metadataURI;\n uint16 marketplaceFeePercent; // 10000 is 100%\n bool lenderAttestationRequired;\n EnumerableSet.AddressSet verifiedLendersForMarket;\n mapping(address => bytes32) lenderAttestationIds;\n uint32 paymentCycleDuration; // unix time (seconds)\n uint32 paymentDefaultDuration; //unix time\n uint32 bidExpirationTime; //unix time\n bool borrowerAttestationRequired;\n EnumerableSet.AddressSet verifiedBorrowersForMarket;\n mapping(address => bytes32) borrowerAttestationIds;\n address feeRecipient;\n PaymentType paymentType;\n PaymentCycleType paymentCycleType;\n }\n\n bytes32 public lenderAttestationSchemaId;\n\n mapping(uint256 => Marketplace) internal markets;\n mapping(bytes32 => uint256) internal __uriToId; //DEPRECATED\n uint256 public marketCount;\n bytes32 private _attestingSchemaId;\n bytes32 public borrowerAttestationSchemaId;\n\n uint256 public version;\n\n mapping(uint256 => bool) private marketIsClosed;\n\n TellerAS public tellerAS;\n\n /* Modifiers */\n\n modifier ownsMarket(uint256 _marketId) {\n require(_getMarketOwner(_marketId) == _msgSender(), \"Not the owner\");\n _;\n }\n\n modifier withAttestingSchema(bytes32 schemaId) {\n _attestingSchemaId = schemaId;\n _;\n _attestingSchemaId = bytes32(0);\n }\n\n /* Events */\n\n event MarketCreated(address indexed owner, uint256 marketId);\n event SetMarketURI(uint256 marketId, string uri);\n event SetPaymentCycleDuration(uint256 marketId, uint32 duration); // DEPRECATED - used for subgraph reference\n event SetPaymentCycle(\n uint256 marketId,\n PaymentCycleType paymentCycleType,\n uint32 value\n );\n event SetPaymentDefaultDuration(uint256 marketId, uint32 duration);\n event SetBidExpirationTime(uint256 marketId, uint32 duration);\n event SetMarketFee(uint256 marketId, uint16 feePct);\n event LenderAttestation(uint256 marketId, address lender);\n event BorrowerAttestation(uint256 marketId, address borrower);\n event LenderRevocation(uint256 marketId, address lender);\n event BorrowerRevocation(uint256 marketId, address borrower);\n event MarketClosed(uint256 marketId);\n event LenderExitMarket(uint256 marketId, address lender);\n event BorrowerExitMarket(uint256 marketId, address borrower);\n event SetMarketOwner(uint256 marketId, address newOwner);\n event SetMarketFeeRecipient(uint256 marketId, address newRecipient);\n event SetMarketLenderAttestation(uint256 marketId, bool required);\n event SetMarketBorrowerAttestation(uint256 marketId, bool required);\n event SetMarketPaymentType(uint256 marketId, PaymentType paymentType);\n\n /* External Functions */\n\n function initialize(TellerAS _tellerAS) external initializer {\n tellerAS = _tellerAS;\n\n lenderAttestationSchemaId = tellerAS.getASRegistry().register(\n \"(uint256 marketId, address lenderAddress)\",\n this\n );\n borrowerAttestationSchemaId = tellerAS.getASRegistry().register(\n \"(uint256 marketId, address borrowerAddress)\",\n this\n );\n }\n\n /**\n * @notice Creates a new market.\n * @param _initialOwner Address who will initially own the market.\n * @param _paymentCycleDuration Length of time in seconds before a bid's next payment is required to be made.\n * @param _paymentDefaultDuration Length of time in seconds before a loan is considered in default for non-payment.\n * @param _bidExpirationTime Length of time in seconds before pending bids expire.\n * @param _requireLenderAttestation Boolean that indicates if lenders require attestation to join market.\n * @param _requireBorrowerAttestation Boolean that indicates if borrowers require attestation to join market.\n * @param _paymentType The payment type for loans in the market.\n * @param _uri URI string to get metadata details about the market.\n * @param _paymentCycleType The payment cycle type for loans in the market - Seconds or Monthly\n * @return marketId_ The market ID of the newly created market.\n */\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n PaymentType _paymentType,\n PaymentCycleType _paymentCycleType,\n string calldata _uri\n ) external returns (uint256 marketId_) {\n marketId_ = _createMarket(\n _initialOwner,\n _paymentCycleDuration,\n _paymentDefaultDuration,\n _bidExpirationTime,\n _feePercent,\n _requireLenderAttestation,\n _requireBorrowerAttestation,\n _paymentType,\n _paymentCycleType,\n _uri\n );\n }\n\n /**\n * @notice Creates a new market.\n * @dev Uses the default EMI payment type.\n * @param _initialOwner Address who will initially own the market.\n * @param _paymentCycleDuration Length of time in seconds before a bid's next payment is required to be made.\n * @param _paymentDefaultDuration Length of time in seconds before a loan is considered in default for non-payment.\n * @param _bidExpirationTime Length of time in seconds before pending bids expire.\n * @param _requireLenderAttestation Boolean that indicates if lenders require attestation to join market.\n * @param _requireBorrowerAttestation Boolean that indicates if borrowers require attestation to join market.\n * @param _uri URI string to get metadata details about the market.\n * @return marketId_ The market ID of the newly created market.\n */\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n string calldata _uri\n ) external returns (uint256 marketId_) {\n marketId_ = _createMarket(\n _initialOwner,\n _paymentCycleDuration,\n _paymentDefaultDuration,\n _bidExpirationTime,\n _feePercent,\n _requireLenderAttestation,\n _requireBorrowerAttestation,\n PaymentType.EMI,\n PaymentCycleType.Seconds,\n _uri\n );\n }\n\n /**\n * @notice Creates a new market.\n * @param _initialOwner Address who will initially own the market.\n * @param _paymentCycleDuration Length of time in seconds before a bid's next payment is required to be made.\n * @param _paymentDefaultDuration Length of time in seconds before a loan is considered in default for non-payment.\n * @param _bidExpirationTime Length of time in seconds before pending bids expire.\n * @param _requireLenderAttestation Boolean that indicates if lenders require attestation to join market.\n * @param _requireBorrowerAttestation Boolean that indicates if borrowers require attestation to join market.\n * @param _paymentType The payment type for loans in the market.\n * @param _uri URI string to get metadata details about the market.\n * @param _paymentCycleType The payment cycle type for loans in the market - Seconds or Monthly\n * @return marketId_ The market ID of the newly created market.\n */\n function _createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n PaymentType _paymentType,\n PaymentCycleType _paymentCycleType,\n string calldata _uri\n ) internal returns (uint256 marketId_) {\n require(_initialOwner != address(0), \"Invalid owner address\");\n // Increment market ID counter\n marketId_ = ++marketCount;\n\n // Set the market owner\n markets[marketId_].owner = _initialOwner;\n\n // Initialize market settings\n _setMarketSettings(\n marketId_,\n _paymentCycleDuration,\n _paymentType,\n _paymentCycleType,\n _paymentDefaultDuration,\n _bidExpirationTime,\n _feePercent,\n _requireBorrowerAttestation,\n _requireLenderAttestation,\n _uri\n );\n\n emit MarketCreated(_initialOwner, marketId_);\n }\n\n /**\n * @notice Closes a market so new bids cannot be added.\n * @param _marketId The market ID for the market to close.\n */\n\n function closeMarket(uint256 _marketId) public ownsMarket(_marketId) {\n if (!marketIsClosed[_marketId]) {\n marketIsClosed[_marketId] = true;\n\n emit MarketClosed(_marketId);\n }\n }\n\n /**\n * @notice Returns the status of a market existing and not being closed.\n * @param _marketId The market ID for the market to check.\n */\n function isMarketOpen(uint256 _marketId)\n public\n view\n override\n returns (bool)\n {\n return\n markets[_marketId].owner != address(0) &&\n !marketIsClosed[_marketId];\n }\n\n /**\n * @notice Returns the status of a market being open or closed for new bids. Does not indicate whether or not a market exists.\n * @param _marketId The market ID for the market to check.\n */\n function isMarketClosed(uint256 _marketId)\n public\n view\n override\n returns (bool)\n {\n return marketIsClosed[_marketId];\n }\n\n /**\n * @notice Adds a lender to a market.\n * @dev See {_attestStakeholder}.\n */\n function attestLender(\n uint256 _marketId,\n address _lenderAddress,\n uint256 _expirationTime\n ) external {\n _attestStakeholder(_marketId, _lenderAddress, _expirationTime, true);\n }\n\n /**\n * @notice Adds a lender to a market via delegated attestation.\n * @dev See {_attestStakeholderViaDelegation}.\n */\n function attestLender(\n uint256 _marketId,\n address _lenderAddress,\n uint256 _expirationTime,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) external {\n _attestStakeholderViaDelegation(\n _marketId,\n _lenderAddress,\n _expirationTime,\n true,\n _v,\n _r,\n _s\n );\n }\n\n /**\n * @notice Removes a lender from an market.\n * @dev See {_revokeStakeholder}.\n */\n function revokeLender(uint256 _marketId, address _lenderAddress) external {\n _revokeStakeholder(_marketId, _lenderAddress, true);\n }\n\n /**\n * @notice Removes a borrower from a market via delegated revocation.\n * @dev See {_revokeStakeholderViaDelegation}.\n */\n function revokeLender(\n uint256 _marketId,\n address _lenderAddress,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) external {\n _revokeStakeholderViaDelegation(\n _marketId,\n _lenderAddress,\n true,\n _v,\n _r,\n _s\n );\n }\n\n /**\n * @notice Allows a lender to voluntarily leave a market.\n * @param _marketId The market ID to leave.\n */\n function lenderExitMarket(uint256 _marketId) external {\n // Remove lender address from market set\n bool response = markets[_marketId].verifiedLendersForMarket.remove(\n _msgSender()\n );\n if (response) {\n emit LenderExitMarket(_marketId, _msgSender());\n }\n }\n\n /**\n * @notice Adds a borrower to a market.\n * @dev See {_attestStakeholder}.\n */\n function attestBorrower(\n uint256 _marketId,\n address _borrowerAddress,\n uint256 _expirationTime\n ) external {\n _attestStakeholder(_marketId, _borrowerAddress, _expirationTime, false);\n }\n\n /**\n * @notice Adds a borrower to a market via delegated attestation.\n * @dev See {_attestStakeholderViaDelegation}.\n */\n function attestBorrower(\n uint256 _marketId,\n address _borrowerAddress,\n uint256 _expirationTime,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) external {\n _attestStakeholderViaDelegation(\n _marketId,\n _borrowerAddress,\n _expirationTime,\n false,\n _v,\n _r,\n _s\n );\n }\n\n /**\n * @notice Removes a borrower from an market.\n * @dev See {_revokeStakeholder}.\n */\n function revokeBorrower(uint256 _marketId, address _borrowerAddress)\n external\n {\n _revokeStakeholder(_marketId, _borrowerAddress, false);\n }\n\n /**\n * @notice Removes a borrower from a market via delegated revocation.\n * @dev See {_revokeStakeholderViaDelegation}.\n */\n function revokeBorrower(\n uint256 _marketId,\n address _borrowerAddress,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) external {\n _revokeStakeholderViaDelegation(\n _marketId,\n _borrowerAddress,\n false,\n _v,\n _r,\n _s\n );\n }\n\n /**\n * @notice Allows a borrower to voluntarily leave a market.\n * @param _marketId The market ID to leave.\n */\n function borrowerExitMarket(uint256 _marketId) external {\n // Remove borrower address from market set\n bool response = markets[_marketId].verifiedBorrowersForMarket.remove(\n _msgSender()\n );\n if (response) {\n emit BorrowerExitMarket(_marketId, _msgSender());\n }\n }\n\n /**\n * @notice Verifies an attestation is valid.\n * @dev This function must only be called by the `attestLender` function above.\n * @param recipient Lender's address who is being attested.\n * @param schema The schema used for the attestation.\n * @param data Data the must include the market ID and lender's address\n * @param\n * @param attestor Market owner's address who signed the attestation.\n * @return Boolean indicating the attestation was successful.\n */\n function resolve(\n address recipient,\n bytes calldata schema,\n bytes calldata data,\n uint256 /* expirationTime */,\n address attestor\n ) external payable override returns (bool) {\n bytes32 attestationSchemaId = keccak256(\n abi.encodePacked(schema, address(this))\n );\n (uint256 marketId, address lenderAddress) = abi.decode(\n data,\n (uint256, address)\n );\n return\n (_attestingSchemaId == attestationSchemaId &&\n recipient == lenderAddress &&\n attestor == _getMarketOwner(marketId)) ||\n attestor == address(this);\n }\n\n /**\n * @notice Transfers ownership of a marketplace.\n * @param _marketId The ID of a market.\n * @param _newOwner Address of the new market owner.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function transferMarketOwnership(uint256 _marketId, address _newOwner)\n public\n ownsMarket(_marketId)\n {\n markets[_marketId].owner = _newOwner;\n emit SetMarketOwner(_marketId, _newOwner);\n }\n\n /**\n * @notice Updates multiple market settings for a given market.\n * @param _marketId The ID of a market.\n * @param _paymentCycleDuration Delinquency duration for new loans\n * @param _newPaymentType The payment type for the market.\n * @param _paymentCycleType The payment cycle type for loans in the market - Seconds or Monthly\n * @param _paymentDefaultDuration Default duration for new loans\n * @param _bidExpirationTime Duration of time before a bid is considered out of date\n * @param _metadataURI A URI that points to a market's metadata.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function updateMarketSettings(\n uint256 _marketId,\n uint32 _paymentCycleDuration,\n PaymentType _newPaymentType,\n PaymentCycleType _paymentCycleType,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _borrowerAttestationRequired,\n bool _lenderAttestationRequired,\n string calldata _metadataURI\n ) public ownsMarket(_marketId) {\n _setMarketSettings(\n _marketId,\n _paymentCycleDuration,\n _newPaymentType,\n _paymentCycleType,\n _paymentDefaultDuration,\n _bidExpirationTime,\n _feePercent,\n _borrowerAttestationRequired,\n _lenderAttestationRequired,\n _metadataURI\n );\n }\n\n /**\n * @notice Sets the fee recipient address for a market.\n * @param _marketId The ID of a market.\n * @param _recipient Address of the new fee recipient.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setMarketFeeRecipient(uint256 _marketId, address _recipient)\n public\n ownsMarket(_marketId)\n {\n markets[_marketId].feeRecipient = _recipient;\n emit SetMarketFeeRecipient(_marketId, _recipient);\n }\n\n /**\n * @notice Sets the metadata URI for a market.\n * @param _marketId The ID of a market.\n * @param _uri A URI that points to a market's metadata.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setMarketURI(uint256 _marketId, string calldata _uri)\n public\n ownsMarket(_marketId)\n {\n //We do string comparison by checking the hashes of the strings against one another\n if (\n keccak256(abi.encodePacked(_uri)) !=\n keccak256(abi.encodePacked(markets[_marketId].metadataURI))\n ) {\n markets[_marketId].metadataURI = _uri;\n\n emit SetMarketURI(_marketId, _uri);\n }\n }\n\n /**\n * @notice Sets the duration of new loans for this market before they turn delinquent.\n * @notice Changing this value does not change the terms of existing loans for this market.\n * @param _marketId The ID of a market.\n * @param _paymentCycleType Cycle type (seconds or monthly)\n * @param _duration Delinquency duration for new loans\n */\n function setPaymentCycle(\n uint256 _marketId,\n PaymentCycleType _paymentCycleType,\n uint32 _duration\n ) public ownsMarket(_marketId) {\n require(\n (_paymentCycleType == PaymentCycleType.Seconds) ||\n (_paymentCycleType == PaymentCycleType.Monthly &&\n _duration == 0),\n \"monthly payment cycle duration cannot be set\"\n );\n Marketplace storage market = markets[_marketId];\n uint32 duration = _paymentCycleType == PaymentCycleType.Seconds\n ? _duration\n : 30 days;\n if (\n _paymentCycleType != market.paymentCycleType ||\n duration != market.paymentCycleDuration\n ) {\n markets[_marketId].paymentCycleType = _paymentCycleType;\n markets[_marketId].paymentCycleDuration = duration;\n\n emit SetPaymentCycle(_marketId, _paymentCycleType, duration);\n }\n }\n\n /**\n * @notice Sets the duration of new loans for this market before they turn defaulted.\n * @notice Changing this value does not change the terms of existing loans for this market.\n * @param _marketId The ID of a market.\n * @param _duration Default duration for new loans\n */\n function setPaymentDefaultDuration(uint256 _marketId, uint32 _duration)\n public\n ownsMarket(_marketId)\n {\n if (_duration != markets[_marketId].paymentDefaultDuration) {\n markets[_marketId].paymentDefaultDuration = _duration;\n\n emit SetPaymentDefaultDuration(_marketId, _duration);\n }\n }\n\n function setBidExpirationTime(uint256 _marketId, uint32 _duration)\n public\n ownsMarket(_marketId)\n {\n if (_duration != markets[_marketId].bidExpirationTime) {\n markets[_marketId].bidExpirationTime = _duration;\n\n emit SetBidExpirationTime(_marketId, _duration);\n }\n }\n\n /**\n * @notice Sets the fee for the market.\n * @param _marketId The ID of a market.\n * @param _newPercent The percentage fee in basis points.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setMarketFeePercent(uint256 _marketId, uint16 _newPercent)\n public\n ownsMarket(_marketId)\n {\n require(_newPercent >= 0 && _newPercent <= 10000, \"invalid percent\");\n if (_newPercent != markets[_marketId].marketplaceFeePercent) {\n markets[_marketId].marketplaceFeePercent = _newPercent;\n emit SetMarketFee(_marketId, _newPercent);\n }\n }\n\n /**\n * @notice Set the payment type for the market.\n * @param _marketId The ID of the market.\n * @param _newPaymentType The payment type for the market.\n */\n function setMarketPaymentType(\n uint256 _marketId,\n PaymentType _newPaymentType\n ) public ownsMarket(_marketId) {\n if (_newPaymentType != markets[_marketId].paymentType) {\n markets[_marketId].paymentType = _newPaymentType;\n emit SetMarketPaymentType(_marketId, _newPaymentType);\n }\n }\n\n /**\n * @notice Enable/disables market whitelist for lenders.\n * @param _marketId The ID of a market.\n * @param _required Boolean indicating if the market requires whitelist.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setLenderAttestationRequired(uint256 _marketId, bool _required)\n public\n ownsMarket(_marketId)\n {\n if (_required != markets[_marketId].lenderAttestationRequired) {\n markets[_marketId].lenderAttestationRequired = _required;\n emit SetMarketLenderAttestation(_marketId, _required);\n }\n }\n\n /**\n * @notice Enable/disables market whitelist for borrowers.\n * @param _marketId The ID of a market.\n * @param _required Boolean indicating if the market requires whitelist.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setBorrowerAttestationRequired(uint256 _marketId, bool _required)\n public\n ownsMarket(_marketId)\n {\n if (_required != markets[_marketId].borrowerAttestationRequired) {\n markets[_marketId].borrowerAttestationRequired = _required;\n emit SetMarketBorrowerAttestation(_marketId, _required);\n }\n }\n\n /**\n * @notice Gets the data associated with a market.\n * @param _marketId The ID of a market.\n */\n function getMarketData(uint256 _marketId)\n public\n view\n returns (\n address owner,\n uint32 paymentCycleDuration,\n uint32 paymentDefaultDuration,\n uint32 loanExpirationTime,\n string memory metadataURI,\n uint16 marketplaceFeePercent,\n bool lenderAttestationRequired\n )\n {\n return (\n markets[_marketId].owner,\n markets[_marketId].paymentCycleDuration,\n markets[_marketId].paymentDefaultDuration,\n markets[_marketId].bidExpirationTime,\n markets[_marketId].metadataURI,\n markets[_marketId].marketplaceFeePercent,\n markets[_marketId].lenderAttestationRequired\n );\n }\n\n /**\n * @notice Gets the attestation requirements for a given market.\n * @param _marketId The ID of the market.\n */\n function getMarketAttestationRequirements(uint256 _marketId)\n public\n view\n returns (\n bool lenderAttestationRequired,\n bool borrowerAttestationRequired\n )\n {\n return (\n markets[_marketId].lenderAttestationRequired,\n markets[_marketId].borrowerAttestationRequired\n );\n }\n\n /**\n * @notice Gets the address of a market's owner.\n * @param _marketId The ID of a market.\n * @return The address of a market's owner.\n */\n function getMarketOwner(uint256 _marketId)\n public\n view\n virtual\n override\n returns (address)\n {\n return _getMarketOwner(_marketId);\n }\n\n /**\n * @notice Gets the address of a market's owner.\n * @param _marketId The ID of a market.\n * @return The address of a market's owner.\n */\n function _getMarketOwner(uint256 _marketId)\n internal\n view\n virtual\n returns (address)\n {\n return markets[_marketId].owner;\n }\n\n /**\n * @notice Gets the fee recipient of a market.\n * @param _marketId The ID of a market.\n * @return The address of a market's fee recipient.\n */\n function getMarketFeeRecipient(uint256 _marketId)\n public\n view\n override\n returns (address)\n {\n address recipient = markets[_marketId].feeRecipient;\n\n if (recipient == address(0)) {\n return _getMarketOwner(_marketId);\n }\n\n return recipient;\n }\n\n /**\n * @notice Gets the metadata URI of a market.\n * @param _marketId The ID of a market.\n * @return URI of a market's metadata.\n */\n function getMarketURI(uint256 _marketId)\n public\n view\n override\n returns (string memory)\n {\n return markets[_marketId].metadataURI;\n }\n\n /**\n * @notice Gets the loan delinquent duration of a market.\n * @param _marketId The ID of a market.\n * @return Duration of a loan until it is delinquent.\n * @return The type of payment cycle for loans in the market.\n */\n function getPaymentCycle(uint256 _marketId)\n public\n view\n override\n returns (uint32, PaymentCycleType)\n {\n return (\n markets[_marketId].paymentCycleDuration,\n markets[_marketId].paymentCycleType\n );\n }\n\n /**\n * @notice Gets the loan default duration of a market.\n * @param _marketId The ID of a market.\n * @return Duration of a loan repayment interval until it is default.\n */\n function getPaymentDefaultDuration(uint256 _marketId)\n public\n view\n override\n returns (uint32)\n {\n return markets[_marketId].paymentDefaultDuration;\n }\n\n /**\n * @notice Get the payment type of a market.\n * @param _marketId the ID of the market.\n * @return The type of payment for loans in the market.\n */\n function getPaymentType(uint256 _marketId)\n public\n view\n override\n returns (PaymentType)\n {\n return markets[_marketId].paymentType;\n }\n\n function getBidExpirationTime(uint256 marketId)\n public\n view\n override\n returns (uint32)\n {\n return markets[marketId].bidExpirationTime;\n }\n\n /**\n * @notice Gets the marketplace fee in basis points\n * @param _marketId The ID of a market.\n * @return fee in basis points\n */\n function getMarketplaceFee(uint256 _marketId)\n public\n view\n override\n returns (uint16 fee)\n {\n return markets[_marketId].marketplaceFeePercent;\n }\n\n /**\n * @notice Checks if a lender has been attested and added to a market.\n * @param _marketId The ID of a market.\n * @param _lenderAddress Address to check.\n * @return isVerified_ Boolean indicating if a lender has been added to a market.\n * @return uuid_ Bytes32 representing the UUID of the lender.\n */\n function isVerifiedLender(uint256 _marketId, address _lenderAddress)\n public\n view\n override\n returns (bool isVerified_, bytes32 uuid_)\n {\n return\n _isVerified(\n _lenderAddress,\n markets[_marketId].lenderAttestationRequired,\n markets[_marketId].lenderAttestationIds,\n markets[_marketId].verifiedLendersForMarket\n );\n }\n\n /**\n * @notice Checks if a borrower has been attested and added to a market.\n * @param _marketId The ID of a market.\n * @param _borrowerAddress Address of the borrower to check.\n * @return isVerified_ Boolean indicating if a borrower has been added to a market.\n * @return uuid_ Bytes32 representing the UUID of the borrower.\n */\n function isVerifiedBorrower(uint256 _marketId, address _borrowerAddress)\n public\n view\n override\n returns (bool isVerified_, bytes32 uuid_)\n {\n return\n _isVerified(\n _borrowerAddress,\n markets[_marketId].borrowerAttestationRequired,\n markets[_marketId].borrowerAttestationIds,\n markets[_marketId].verifiedBorrowersForMarket\n );\n }\n\n /**\n * @notice Gets addresses of all attested lenders.\n * @param _marketId The ID of a market.\n * @param _page Page index to start from.\n * @param _perPage Number of items in a page to return.\n * @return Array of addresses that have been added to a market.\n */\n function getAllVerifiedLendersForMarket(\n uint256 _marketId,\n uint256 _page,\n uint256 _perPage\n ) public view returns (address[] memory) {\n EnumerableSet.AddressSet storage set = markets[_marketId]\n .verifiedLendersForMarket;\n\n return _getStakeholdersForMarket(set, _page, _perPage);\n }\n\n /**\n * @notice Gets addresses of all attested borrowers.\n * @param _marketId The ID of the market.\n * @param _page Page index to start from.\n * @param _perPage Number of items in a page to return.\n * @return Array of addresses that have been added to a market.\n */\n function getAllVerifiedBorrowersForMarket(\n uint256 _marketId,\n uint256 _page,\n uint256 _perPage\n ) public view returns (address[] memory) {\n EnumerableSet.AddressSet storage set = markets[_marketId]\n .verifiedBorrowersForMarket;\n return _getStakeholdersForMarket(set, _page, _perPage);\n }\n\n /**\n * @notice Sets multiple market settings for a given market.\n * @param _marketId The ID of a market.\n * @param _paymentCycleDuration Delinquency duration for new loans\n * @param _newPaymentType The payment type for the market.\n * @param _paymentCycleType The payment cycle type for loans in the market - Seconds or Monthly\n * @param _paymentDefaultDuration Default duration for new loans\n * @param _bidExpirationTime Duration of time before a bid is considered out of date\n * @param _metadataURI A URI that points to a market's metadata.\n */\n function _setMarketSettings(\n uint256 _marketId,\n uint32 _paymentCycleDuration,\n PaymentType _newPaymentType,\n PaymentCycleType _paymentCycleType,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _borrowerAttestationRequired,\n bool _lenderAttestationRequired,\n string calldata _metadataURI\n ) internal {\n setMarketURI(_marketId, _metadataURI);\n setPaymentDefaultDuration(_marketId, _paymentDefaultDuration);\n setBidExpirationTime(_marketId, _bidExpirationTime);\n setMarketFeePercent(_marketId, _feePercent);\n setLenderAttestationRequired(_marketId, _lenderAttestationRequired);\n setBorrowerAttestationRequired(_marketId, _borrowerAttestationRequired);\n setMarketPaymentType(_marketId, _newPaymentType);\n setPaymentCycle(_marketId, _paymentCycleType, _paymentCycleDuration);\n }\n\n /**\n * @notice Gets addresses of all attested relevant stakeholders.\n * @param _set The stored set of stakeholders to index from.\n * @param _page Page index to start from.\n * @param _perPage Number of items in a page to return.\n * @return stakeholders_ Array of addresses that have been added to a market.\n */\n function _getStakeholdersForMarket(\n EnumerableSet.AddressSet storage _set,\n uint256 _page,\n uint256 _perPage\n ) internal view returns (address[] memory stakeholders_) {\n uint256 len = _set.length();\n\n uint256 start = _page * _perPage;\n if (start <= len) {\n uint256 end = start + _perPage;\n // Ensure we do not go out of bounds\n if (end > len) {\n end = len;\n }\n\n stakeholders_ = new address[](end - start);\n for (uint256 i = start; i < end; i++) {\n stakeholders_[i] = _set.at(i);\n }\n }\n }\n\n /* Internal Functions */\n\n /**\n * @notice Adds a stakeholder (lender or borrower) to a market.\n * @param _marketId The market ID to add a borrower to.\n * @param _stakeholderAddress The address of the stakeholder to add to the market.\n * @param _expirationTime The expiration time of the attestation.\n * @param _expirationTime The expiration time of the attestation.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n */\n function _attestStakeholder(\n uint256 _marketId,\n address _stakeholderAddress,\n uint256 _expirationTime,\n bool _isLender\n )\n internal\n virtual\n withAttestingSchema(\n _isLender ? lenderAttestationSchemaId : borrowerAttestationSchemaId\n )\n {\n require(\n _msgSender() == _getMarketOwner(_marketId),\n \"Not the market owner\"\n );\n\n // Submit attestation for borrower to join a market\n bytes32 uuid = tellerAS.attest(\n _stakeholderAddress,\n _attestingSchemaId, // set by the modifier\n _expirationTime,\n 0,\n abi.encode(_marketId, _stakeholderAddress)\n );\n _attestStakeholderVerification(\n _marketId,\n _stakeholderAddress,\n uuid,\n _isLender\n );\n }\n\n /**\n * @notice Adds a stakeholder (lender or borrower) to a market via delegated attestation.\n * @dev The signature must match that of the market owner.\n * @param _marketId The market ID to add a lender to.\n * @param _stakeholderAddress The address of the lender to add to the market.\n * @param _expirationTime The expiration time of the attestation.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n * @param _v Signature value\n * @param _r Signature value\n * @param _s Signature value\n */\n function _attestStakeholderViaDelegation(\n uint256 _marketId,\n address _stakeholderAddress,\n uint256 _expirationTime,\n bool _isLender,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n )\n internal\n virtual\n withAttestingSchema(\n _isLender ? lenderAttestationSchemaId : borrowerAttestationSchemaId\n )\n {\n // NOTE: block scope to prevent stack too deep!\n bytes32 uuid;\n {\n bytes memory data = abi.encode(_marketId, _stakeholderAddress);\n address attestor = _getMarketOwner(_marketId);\n // Submit attestation for stakeholder to join a market (attestation must be signed by market owner)\n uuid = tellerAS.attestByDelegation(\n _stakeholderAddress,\n _attestingSchemaId, // set by the modifier\n _expirationTime,\n 0,\n data,\n attestor,\n _v,\n _r,\n _s\n );\n }\n _attestStakeholderVerification(\n _marketId,\n _stakeholderAddress,\n uuid,\n _isLender\n );\n }\n\n /**\n * @notice Adds a stakeholder (borrower/lender) to a market.\n * @param _marketId The market ID to add a stakeholder to.\n * @param _stakeholderAddress The address of the stakeholder to add to the market.\n * @param _uuid The UUID of the attestation created.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n */\n function _attestStakeholderVerification(\n uint256 _marketId,\n address _stakeholderAddress,\n bytes32 _uuid,\n bool _isLender\n ) internal virtual {\n if (_isLender) {\n // Store the lender attestation ID for the market ID\n markets[_marketId].lenderAttestationIds[\n _stakeholderAddress\n ] = _uuid;\n // Add lender address to market set\n markets[_marketId].verifiedLendersForMarket.add(\n _stakeholderAddress\n );\n\n emit LenderAttestation(_marketId, _stakeholderAddress);\n } else {\n // Store the lender attestation ID for the market ID\n markets[_marketId].borrowerAttestationIds[\n _stakeholderAddress\n ] = _uuid;\n // Add lender address to market set\n markets[_marketId].verifiedBorrowersForMarket.add(\n _stakeholderAddress\n );\n\n emit BorrowerAttestation(_marketId, _stakeholderAddress);\n }\n }\n\n /**\n * @notice Removes a stakeholder from an market.\n * @dev The caller must be the market owner.\n * @param _marketId The market ID to remove the borrower from.\n * @param _stakeholderAddress The address of the borrower to remove from the market.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n */\n function _revokeStakeholder(\n uint256 _marketId,\n address _stakeholderAddress,\n bool _isLender\n ) internal virtual {\n require(\n _msgSender() == _getMarketOwner(_marketId),\n \"Not the market owner\"\n );\n\n bytes32 uuid = _revokeStakeholderVerification(\n _marketId,\n _stakeholderAddress,\n _isLender\n );\n // NOTE: Disabling the call to revoke the attestation on EAS contracts\n // tellerAS.revoke(uuid);\n }\n\n /**\n * @notice Removes a stakeholder from an market via delegated revocation.\n * @param _marketId The market ID to remove the borrower from.\n * @param _stakeholderAddress The address of the borrower to remove from the market.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n * @param _v Signature value\n * @param _r Signature value\n * @param _s Signature value\n */\n function _revokeStakeholderViaDelegation(\n uint256 _marketId,\n address _stakeholderAddress,\n bool _isLender,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) internal {\n bytes32 uuid = _revokeStakeholderVerification(\n _marketId,\n _stakeholderAddress,\n _isLender\n );\n // NOTE: Disabling the call to revoke the attestation on EAS contracts\n // address attestor = markets[_marketId].owner;\n // tellerAS.revokeByDelegation(uuid, attestor, _v, _r, _s);\n }\n\n /**\n * @notice Removes a stakeholder (borrower/lender) from a market.\n * @param _marketId The market ID to remove the lender from.\n * @param _stakeholderAddress The address of the stakeholder to remove from the market.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n * @return uuid_ The ID of the previously verified attestation.\n */\n function _revokeStakeholderVerification(\n uint256 _marketId,\n address _stakeholderAddress,\n bool _isLender\n ) internal virtual returns (bytes32 uuid_) {\n if (_isLender) {\n uuid_ = markets[_marketId].lenderAttestationIds[\n _stakeholderAddress\n ];\n // Remove lender address from market set\n markets[_marketId].verifiedLendersForMarket.remove(\n _stakeholderAddress\n );\n\n emit LenderRevocation(_marketId, _stakeholderAddress);\n } else {\n uuid_ = markets[_marketId].borrowerAttestationIds[\n _stakeholderAddress\n ];\n // Remove borrower address from market set\n markets[_marketId].verifiedBorrowersForMarket.remove(\n _stakeholderAddress\n );\n\n emit BorrowerRevocation(_marketId, _stakeholderAddress);\n }\n }\n\n /**\n * @notice Checks if a stakeholder has been attested and added to a market.\n * @param _stakeholderAddress Address of the stakeholder to check.\n * @param _attestationRequired Stored boolean indicating if attestation is required for the stakeholder class.\n * @param _stakeholderAttestationIds Mapping of attested Ids for the stakeholder class.\n */\n function _isVerified(\n address _stakeholderAddress,\n bool _attestationRequired,\n mapping(address => bytes32) storage _stakeholderAttestationIds,\n EnumerableSet.AddressSet storage _verifiedStakeholderForMarket\n ) internal view virtual returns (bool isVerified_, bytes32 uuid_) {\n if (_attestationRequired) {\n isVerified_ =\n _verifiedStakeholderForMarket.contains(_stakeholderAddress) &&\n tellerAS.isAttestationActive(\n _stakeholderAttestationIds[_stakeholderAddress]\n );\n uuid_ = _stakeholderAttestationIds[_stakeholderAddress];\n } else {\n isVerified_ = true;\n }\n }\n}\n" + }, + "contracts/MetaForwarder.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts-upgradeable/metatx/MinimalForwarderUpgradeable.sol\";\n\ncontract MetaForwarder is MinimalForwarderUpgradeable {\n function initialize() external initializer {\n __EIP712_init_unchained(\"TellerMetaForwarder\", \"0.0.1\");\n }\n}\n" + }, + "contracts/mock/aave/AavePoolAddressProviderMock.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\n/**\n * @title PoolAddressesProvider\n * @author Aave\n * @notice Main registry of addresses part of or connected to the protocol, including permissioned roles\n * @dev Acts as factory of proxies and admin of those, so with right to change its implementations\n * @dev Owned by the Aave Governance\n */\ncontract AavePoolAddressProviderMock is Ownable, IPoolAddressesProvider {\n // Identifier of the Aave Market\n string private _marketId;\n\n // Map of registered addresses (identifier => registeredAddress)\n mapping(bytes32 => address) private _addresses;\n\n // Main identifiers\n bytes32 private constant POOL = \"POOL\";\n bytes32 private constant POOL_CONFIGURATOR = \"POOL_CONFIGURATOR\";\n bytes32 private constant PRICE_ORACLE = \"PRICE_ORACLE\";\n bytes32 private constant ACL_MANAGER = \"ACL_MANAGER\";\n bytes32 private constant ACL_ADMIN = \"ACL_ADMIN\";\n bytes32 private constant PRICE_ORACLE_SENTINEL = \"PRICE_ORACLE_SENTINEL\";\n bytes32 private constant DATA_PROVIDER = \"DATA_PROVIDER\";\n\n /**\n * @dev Constructor.\n * @param marketId The identifier of the market.\n * @param owner The owner address of this contract.\n */\n constructor(string memory marketId, address owner) {\n _setMarketId(marketId);\n transferOwnership(owner);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getMarketId() external view override returns (string memory) {\n return _marketId;\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function setMarketId(string memory newMarketId)\n external\n override\n onlyOwner\n {\n _setMarketId(newMarketId);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getAddress(bytes32 id) public view override returns (address) {\n return _addresses[id];\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function setAddress(bytes32 id, address newAddress)\n external\n override\n onlyOwner\n {\n address oldAddress = _addresses[id];\n _addresses[id] = newAddress;\n emit AddressSet(id, oldAddress, newAddress);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getPool() external view override returns (address) {\n return getAddress(POOL);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getPoolConfigurator() external view override returns (address) {\n return getAddress(POOL_CONFIGURATOR);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getPriceOracle() external view override returns (address) {\n return getAddress(PRICE_ORACLE);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function setPriceOracle(address newPriceOracle)\n external\n override\n onlyOwner\n {\n address oldPriceOracle = _addresses[PRICE_ORACLE];\n _addresses[PRICE_ORACLE] = newPriceOracle;\n emit PriceOracleUpdated(oldPriceOracle, newPriceOracle);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getACLManager() external view override returns (address) {\n return getAddress(ACL_MANAGER);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function setACLManager(address newAclManager) external override onlyOwner {\n address oldAclManager = _addresses[ACL_MANAGER];\n _addresses[ACL_MANAGER] = newAclManager;\n emit ACLManagerUpdated(oldAclManager, newAclManager);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getACLAdmin() external view override returns (address) {\n return getAddress(ACL_ADMIN);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function setACLAdmin(address newAclAdmin) external override onlyOwner {\n address oldAclAdmin = _addresses[ACL_ADMIN];\n _addresses[ACL_ADMIN] = newAclAdmin;\n emit ACLAdminUpdated(oldAclAdmin, newAclAdmin);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getPriceOracleSentinel() external view override returns (address) {\n return getAddress(PRICE_ORACLE_SENTINEL);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function setPriceOracleSentinel(address newPriceOracleSentinel)\n external\n override\n onlyOwner\n {\n address oldPriceOracleSentinel = _addresses[PRICE_ORACLE_SENTINEL];\n _addresses[PRICE_ORACLE_SENTINEL] = newPriceOracleSentinel;\n emit PriceOracleSentinelUpdated(\n oldPriceOracleSentinel,\n newPriceOracleSentinel\n );\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function getPoolDataProvider() external view override returns (address) {\n return getAddress(DATA_PROVIDER);\n }\n\n /// @inheritdoc IPoolAddressesProvider\n function setPoolDataProvider(address newDataProvider)\n external\n override\n onlyOwner\n {\n address oldDataProvider = _addresses[DATA_PROVIDER];\n _addresses[DATA_PROVIDER] = newDataProvider;\n emit PoolDataProviderUpdated(oldDataProvider, newDataProvider);\n }\n\n /**\n * @notice Updates the identifier of the Aave market.\n * @param newMarketId The new id of the market\n */\n function _setMarketId(string memory newMarketId) internal {\n string memory oldMarketId = _marketId;\n _marketId = newMarketId;\n emit MarketIdSet(oldMarketId, newMarketId);\n }\n\n //removed for the mock\n function setAddressAsProxy(bytes32 id, address newImplementationAddress)\n external\n {}\n\n function setPoolConfiguratorImpl(address newPoolConfiguratorImpl)\n external\n {}\n\n function setPoolImpl(address newPoolImpl) external {}\n}\n" + }, + "contracts/mock/aave/AavePoolMock.sol": { + "content": "pragma solidity ^0.8.0;\n\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract AavePoolMock {\n bool public flashLoanSimpleWasCalled;\n\n bool public shouldExecuteCallback = true;\n\n function setShouldExecuteCallback(bool shouldExecute) public {\n shouldExecuteCallback = shouldExecute;\n }\n\n function flashLoanSimple(\n address receiverAddress,\n address asset,\n uint256 amount,\n bytes calldata params,\n uint16 referralCode\n ) external returns (bool success) {\n uint256 balanceBefore = IERC20(asset).balanceOf(address(this));\n\n IERC20(asset).transfer(receiverAddress, amount);\n\n uint256 premium = amount / 100;\n address initiator = msg.sender;\n\n if (shouldExecuteCallback) {\n success = IFlashLoanSimpleReceiver(receiverAddress)\n .executeOperation(asset, amount, premium, initiator, params);\n\n require(success == true, \"executeOperation failed\");\n }\n\n IERC20(asset).transferFrom(\n receiverAddress,\n address(this),\n amount + premium\n );\n\n //require balance is what it was plus the fee..\n uint256 balanceAfter = IERC20(asset).balanceOf(address(this));\n\n require(\n balanceAfter >= balanceBefore + premium,\n \"Must repay flash loan\"\n );\n\n flashLoanSimpleWasCalled = true;\n }\n}\n" + }, + "contracts/mock/CollateralManagerMock.sol": { + "content": "pragma solidity ^0.8.0;\n\n// SPDX-License-Identifier: MIT\n\nimport \"../interfaces/ICollateralManager.sol\";\n\ncontract CollateralManagerMock is ICollateralManager {\n bool public committedCollateralValid = true;\n bool public deployAndDepositWasCalled;\n\n function commitCollateral(\n uint256 _bidId,\n Collateral[] calldata _collateralInfo\n ) external returns (bool validation_) {\n validation_ = committedCollateralValid;\n }\n\n function commitCollateral(\n uint256 _bidId,\n Collateral calldata _collateralInfo\n ) external returns (bool validation_) {\n validation_ = committedCollateralValid;\n }\n\n function checkBalances(\n address _borrowerAddress,\n Collateral[] calldata _collateralInfo\n ) external returns (bool validated_, bool[] memory checks_) {\n validated_ = true;\n checks_ = new bool[](0);\n }\n\n /**\n * @notice Deploys a new collateral escrow.\n * @param _bidId The associated bidId of the collateral escrow.\n */\n function deployAndDeposit(uint256 _bidId) external {\n deployAndDepositWasCalled = true;\n }\n\n /**\n * @notice Gets the address of a deployed escrow.\n * @notice _bidId The bidId to return the escrow for.\n * @return The address of the escrow.\n */\n function getEscrow(uint256 _bidId) external view returns (address) {\n return address(0);\n }\n\n /**\n * @notice Gets the collateral info for a given bid id.\n * @param _bidId The bidId to return the collateral info for.\n */\n function getCollateralInfo(uint256 _bidId)\n external\n view\n returns (Collateral[] memory collateral_)\n {\n collateral_ = new Collateral[](0);\n }\n\n function getCollateralAmount(uint256 _bidId, address collateralAssetAddress)\n external\n view\n returns (uint256 _amount)\n {\n return 500;\n }\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function withdraw(uint256 _bidId) external {}\n\n /**\n * @notice Re-checks the validity of a borrower's collateral balance committed to a bid.\n * @param _bidId The id of the associated bid.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function revalidateCollateral(uint256 _bidId) external returns (bool) {\n return true;\n }\n\n function lenderClaimCollateral(uint256 _bidId) external {}\n\n function lenderClaimCollateralWithRecipient(uint256 _bidId, address _collateralRecipient) external {}\n\n\n /**\n * @notice Sends the deposited collateral to a liquidator of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n * @param _liquidatorAddress The address of the liquidator to send the collateral to.\n */\n function liquidateCollateral(uint256 _bidId, address _liquidatorAddress)\n external\n {}\n\n function forceSetCommitCollateralValidation(bool _validation) external {\n committedCollateralValid = _validation;\n }\n}\n" + }, + "contracts/mock/LenderCommitmentForwarderMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n//import \"../TellerV2MarketForwarder.sol\";\n\nimport \"../TellerV2Context.sol\";\n\n//import { LenderCommitmentForwarder } from \"../contracts/LenderCommitmentForwarder.sol\";\n\nimport \"../interfaces/ITellerV2.sol\";\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\n\nimport \"../interfaces/ITellerV2MarketForwarder.sol\";\n\nimport { Collateral, CollateralType } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\nimport \"../mock/MarketRegistryMock.sol\";\n\ncontract LenderCommitmentForwarderMock is\n ILenderCommitmentForwarder,\n ITellerV2MarketForwarder\n{\n mapping(uint256 => Commitment) public commitments;\n\n uint256 commitmentCount;\n\n bool public submitBidWithCollateralWasCalled;\n bool public acceptBidWasCalled;\n bool public submitBidWasCalled;\n bool public acceptCommitmentWithRecipientWasCalled;\n bool public acceptCommitmentWithRecipientAndProofWasCalled;\n\n mapping(uint256 => uint256) public commitmentPrincipalAccepted;\n\n constructor() {}\n\n function createCommitment(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList\n ) external returns (uint256) {}\n\n function setCommitment(uint256 _commitmentId, Commitment memory _commitment)\n public\n {\n commitments[_commitmentId] = _commitment;\n }\n\n function getCommitmentLender(uint256 _commitmentId)\n public\n view\n returns (address)\n {\n return commitments[_commitmentId].lender;\n }\n\n function getCommitmentMarketId(uint256 _commitmentId)\n public\n view\n returns (uint256)\n {\n return commitments[_commitmentId].marketId;\n }\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n public\n view\n returns (uint256)\n {\n return commitmentPrincipalAccepted[_commitmentId];\n }\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n public\n view\n returns (uint256)\n {\n return commitments[_commitmentId].maxPrincipal;\n }\n\n /* function _getEscrowCollateralTypeSuper(CommitmentCollateralType _type)\n public\n returns (CollateralType)\n {\n return super._getEscrowCollateralType(_type);\n }\n\n function validateCommitmentSuper(uint256 _commitmentId) public {\n super.validateCommitment(commitments[_commitmentId]);\n }*/\n\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n acceptCommitmentWithRecipientWasCalled = true;\n\n Commitment storage commitment = commitments[_commitmentId];\n\n address lendingToken = commitment.principalTokenAddress;\n\n _mockAcceptCommitmentTokenTransfer(\n lendingToken,\n _principalAmount,\n _recipient\n );\n }\n\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n acceptCommitmentWithRecipientAndProofWasCalled = true;\n\n Commitment storage commitment = commitments[_commitmentId];\n\n address lendingToken = commitment.principalTokenAddress;\n\n _mockAcceptCommitmentTokenTransfer(\n lendingToken,\n _principalAmount,\n _recipient\n );\n }\n\n function _mockAcceptCommitmentTokenTransfer(\n address lendingToken,\n uint256 principalAmount,\n address _recipient\n ) internal {\n IERC20(lendingToken).transfer(_recipient, principalAmount);\n }\n\n /*\n Override methods \n */\n\n /* function _submitBid(CreateLoanArgs memory, address)\n internal\n override\n returns (uint256 bidId)\n {\n submitBidWasCalled = true;\n return 1;\n }\n\n function _submitBidWithCollateral(CreateLoanArgs memory, address)\n internal\n override\n returns (uint256 bidId)\n {\n submitBidWithCollateralWasCalled = true;\n return 1;\n }\n\n function _acceptBid(uint256, address) internal override returns (bool) {\n acceptBidWasCalled = true;\n\n return true;\n }\n */\n}\n" + }, + "contracts/mock/LenderManagerMock.sol": { + "content": "pragma solidity ^0.8.0;\n\n// SPDX-License-Identifier: MIT\n\nimport \"../interfaces/ILenderManager.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\";\n\ncontract LenderManagerMock is ILenderManager, ERC721Upgradeable {\n //bidId => lender\n mapping(uint256 => address) public registeredLoan;\n\n constructor() {}\n\n function registerLoan(uint256 _bidId, address _newLender)\n external\n override\n {\n registeredLoan[_bidId] = _newLender;\n }\n\n function ownerOf(uint256 _bidId)\n public\n view\n override(ERC721Upgradeable, IERC721Upgradeable)\n returns (address)\n {\n return registeredLoan[_bidId];\n }\n}\n" + }, + "contracts/mock/MarketRegistryMock.sol": { + "content": "pragma solidity ^0.8.0;\n\n// SPDX-License-Identifier: MIT\n\nimport \"../interfaces/IMarketRegistry.sol\";\nimport { PaymentType } from \"../libraries/V2Calculations.sol\";\n\ncontract MarketRegistryMock is IMarketRegistry {\n //address marketOwner;\n\n address public globalMarketOwner;\n address public globalMarketFeeRecipient;\n bool public globalMarketsClosed;\n\n bool public globalBorrowerIsVerified = true;\n bool public globalLenderIsVerified = true;\n\n constructor() {}\n\n function initialize(TellerAS _tellerAS) external {}\n\n function isVerifiedLender(uint256 _marketId, address _lenderAddress)\n public\n view\n returns (bool isVerified_, bytes32 uuid_)\n {\n isVerified_ = globalLenderIsVerified;\n }\n\n function isMarketOpen(uint256 _marketId) public view returns (bool) {\n return !globalMarketsClosed;\n }\n\n function isMarketClosed(uint256 _marketId) public view returns (bool) {\n return globalMarketsClosed;\n }\n\n function isVerifiedBorrower(uint256 _marketId, address _borrower)\n public\n view\n returns (bool isVerified_, bytes32 uuid_)\n {\n isVerified_ = globalBorrowerIsVerified;\n }\n\n function getMarketOwner(uint256 _marketId)\n public\n view\n override\n returns (address)\n {\n return address(globalMarketOwner);\n }\n\n function getMarketFeeRecipient(uint256 _marketId)\n public\n view\n returns (address)\n {\n return address(globalMarketFeeRecipient);\n }\n\n function getMarketURI(uint256 _marketId)\n public\n view\n returns (string memory)\n {\n return \"url://\";\n }\n\n function getPaymentCycle(uint256 _marketId)\n public\n view\n returns (uint32, PaymentCycleType)\n {\n return (1000, PaymentCycleType.Seconds);\n }\n\n function getPaymentDefaultDuration(uint256 _marketId)\n public\n view\n returns (uint32)\n {\n return 1000;\n }\n\n function getBidExpirationTime(uint256 _marketId)\n public\n view\n returns (uint32)\n {\n return 1000;\n }\n\n function getMarketplaceFee(uint256 _marketId) public view returns (uint16) {\n return 1000;\n }\n\n function setMarketOwner(address _owner) public {\n globalMarketOwner = _owner;\n }\n\n function setMarketFeeRecipient(address _feeRecipient) public {\n globalMarketFeeRecipient = _feeRecipient;\n }\n\n function getPaymentType(uint256 _marketId)\n public\n view\n returns (PaymentType)\n {}\n\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n PaymentType _paymentType,\n PaymentCycleType _paymentCycleType,\n string calldata _uri\n ) public returns (uint256) {}\n\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n string calldata _uri\n ) public returns (uint256) {}\n\n function closeMarket(uint256 _marketId) public {}\n\n function mock_setGlobalMarketsClosed(bool closed) public {\n globalMarketsClosed = closed;\n }\n\n function mock_setBorrowerIsVerified(bool verified) public {\n globalBorrowerIsVerified = verified;\n }\n\n function mock_setLenderIsVerified(bool verified) public {\n globalLenderIsVerified = verified;\n }\n}\n" + }, + "contracts/mock/ReputationManagerMock.sol": { + "content": "pragma solidity ^0.8.0;\n\n// SPDX-License-Identifier: MIT\n\nimport \"../interfaces/IReputationManager.sol\";\n\ncontract ReputationManagerMock is IReputationManager {\n constructor() {}\n\n function initialize(address protocolAddress) external override {}\n\n function getDelinquentLoanIds(address _account)\n external\n returns (uint256[] memory _loanIds)\n {}\n\n function getDefaultedLoanIds(address _account)\n external\n returns (uint256[] memory _loanIds)\n {}\n\n function getCurrentDelinquentLoanIds(address _account)\n external\n returns (uint256[] memory _loanIds)\n {}\n\n function getCurrentDefaultLoanIds(address _account)\n external\n returns (uint256[] memory _loanIds)\n {}\n\n function updateAccountReputation(address _account) external {}\n\n function updateAccountReputation(address _account, uint256 _bidId)\n external\n returns (RepMark)\n {\n return RepMark.Good;\n }\n}\n" + }, + "contracts/mock/TellerASMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../EAS/TellerAS.sol\";\nimport \"../EAS/TellerASEIP712Verifier.sol\";\nimport \"../EAS/TellerASRegistry.sol\";\n\nimport \"../interfaces/IASRegistry.sol\";\nimport \"../interfaces/IEASEIP712Verifier.sol\";\n\ncontract TellerASMock is TellerAS {\n constructor()\n TellerAS(\n IASRegistry(new TellerASRegistry()),\n IEASEIP712Verifier(new TellerASEIP712Verifier())\n )\n {}\n\n function isAttestationActive(bytes32 uuid)\n public\n view\n override\n returns (bool)\n {\n return true;\n }\n}\n" + }, + "contracts/mock/TellerV2SolMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0 <0.9.0;\n\nimport \"../TellerV2.sol\";\nimport \"../interfaces/ITellerV2.sol\";\nimport \"../interfaces/IProtocolFee.sol\";\nimport \"../TellerV2Context.sol\";\nimport \"../pausing/HasProtocolPausingManager.sol\";\nimport { Collateral } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\nimport { LoanDetails, Payment, BidState } from \"../TellerV2Storage.sol\";\n\nimport { ILoanRepaymentCallbacks } from \"../interfaces/ILoanRepaymentCallbacks.sol\";\n\n\n/*\nThis is only used for sol test so its named specifically to avoid being used for the typescript tests.\n*/\ncontract TellerV2SolMock is \nITellerV2,\nIProtocolFee, \nTellerV2Storage , \nHasProtocolPausingManager,\nILoanRepaymentCallbacks\n{\n uint256 public amountOwedMockPrincipal;\n uint256 public amountOwedMockInterest;\n address public approvedForwarder;\n bool public isPausedMock;\n\n address public mockOwner;\n\n\n PaymentCycleType globalBidPaymentCycleType = PaymentCycleType.Seconds;\n uint32 globalBidPaymentCycleDuration = 3000;\n\n uint256 mockLoanDefaultTimestamp;\n bool public lenderCloseLoanWasCalled;\n\n function setMarketRegistry(address _marketRegistry) public {\n marketRegistry = IMarketRegistry(_marketRegistry);\n }\n\n function setProtocolPausingManager(address _protocolPausingManager) public {\n _setProtocolPausingManager(_protocolPausingManager);\n }\n\n function getMarketRegistry() external view returns (IMarketRegistry) {\n return marketRegistry;\n }\n\n function protocolFee() external view returns (uint16) {\n return 100;\n }\n\n\n function getEscrowVault() external view returns(address){\n return address(0);\n }\n\n\n function paused() external view returns(bool){\n return isPausedMock;\n }\n\n\n function setMockOwner(address _newOwner) external {\n mockOwner = _newOwner;\n }\n function owner() external view returns(address){\n return mockOwner;\n }\n\n function isPauser(address _account) public view returns(bool){\n return false; //for now \n }\n\n function approveMarketForwarder(uint256 _marketId, address _forwarder)\n external\n {\n approvedForwarder = _forwarder;\n }\n\n\n function submitBid(\n address _lendingToken,\n uint256 _marketId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata,\n address _receiver\n ) public returns (uint256 bidId_) {\n \n\n\n bidId_ = bidId;\n\n Bid storage bid = bids[bidId_];\n bid.borrower = msg.sender;\n bid.receiver = _receiver != address(0) ? _receiver : bid.borrower;\n bid.marketplaceId = _marketId;\n bid.loanDetails.lendingToken = IERC20(_lendingToken);\n bid.loanDetails.principal = _principal;\n bid.loanDetails.loanDuration = _duration;\n bid.loanDetails.timestamp = uint32(block.timestamp);\n\n /*(bid.terms.paymentCycle, bidPaymentCycleType[bidId]) = marketRegistry\n .getPaymentCycle(_marketId);*/\n\n bid.terms.APR = _APR;\n\n bidId++; //nextBidId\n\n }\n\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver,\n Collateral[] calldata _collateralInfo\n ) public returns (uint256 bidId_) {\n submitBid(\n _lendingToken,\n _marketplaceId,\n _principal,\n _duration,\n _APR,\n _metadataURI,\n _receiver\n );\n }\n\n function lenderCloseLoan(uint256 _bidId) external {\n lenderCloseLoanWasCalled = true;\n }\n\n function lenderCloseLoanWithRecipient(uint256 _bidId, address _recipient)\n external\n {\n lenderCloseLoanWasCalled = true;\n }\n\n function getLoanDefaultTimestamp(uint256 _bidId)\n external\n view\n returns (uint256)\n {\n return mockLoanDefaultTimestamp;\n }\n\n function liquidateLoanFull(uint256 _bidId) external {}\n\n function liquidateLoanFullWithRecipient(uint256 _bidId, address _recipient)\n external\n {}\n\n function repayLoanMinimum(uint256 _bidId) external {}\n\n function repayLoanFull(uint256 _bidId) external {\n Bid storage bid = bids[_bidId];\n\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bids[_bidId],\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n\n uint256 _amount = owedPrincipal + interest;\n\n IERC20(bid.loanDetails.lendingToken).transferFrom(\n msg.sender,\n address(this),\n _amount\n );\n }\n\n function repayLoan(uint256 _bidId, uint256 _amount) public {\n Bid storage bid = bids[_bidId];\n\n IERC20(bid.loanDetails.lendingToken).transferFrom(\n msg.sender,\n address(this),\n _amount\n );\n }\n\n /*\n * @notice Calculates the minimum payment amount due for a loan.\n * @param _bidId The id of the loan bid to get the payment amount for.\n */\n function calculateAmountDue(uint256 _bidId, uint256 _timestamp)\n public\n view\n returns (Payment memory due)\n {\n if (bids[_bidId].state != BidState.ACCEPTED) return due;\n\n (, uint256 duePrincipal, uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bids[_bidId],\n _timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n due.principal = duePrincipal;\n due.interest = interest;\n }\n\n function calculateAmountOwed(uint256 _bidId, uint256 _timestamp)\n public\n view\n returns (Payment memory due)\n {\n if (bids[_bidId].state != BidState.ACCEPTED) return due;\n\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bids[_bidId],\n _timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n due.principal = owedPrincipal;\n due.interest = interest;\n }\n\n function lenderAcceptBid(uint256 _bidId)\n public\n returns (\n uint256 amountToProtocol,\n uint256 amountToMarketplace,\n uint256 amountToBorrower\n )\n {\n Bid storage bid = bids[_bidId];\n\n bid.lender = msg.sender;\n\n bid.state = BidState.ACCEPTED;\n\n //send tokens to caller\n IERC20(bid.loanDetails.lendingToken).transferFrom(\n bid.lender,\n bid.receiver,\n bid.loanDetails.principal\n );\n //for the reciever\n\n return (0, bid.loanDetails.principal, 0);\n }\n\n function getBidState(uint256 _bidId)\n public\n view\n virtual\n returns (BidState)\n {\n return bids[_bidId].state;\n }\n\n function getLoanDetails(uint256 _bidId)\n public\n view\n returns (LoanDetails memory)\n {\n return bids[_bidId].loanDetails;\n }\n\n function getBorrowerActiveLoanIds(address _borrower)\n public\n view\n returns (uint256[] memory)\n {}\n\n function isLoanDefaulted(uint256 _bidId)\n public\n view\n virtual\n returns (bool)\n {}\n\n function isLoanLiquidateable(uint256 _bidId)\n public\n view\n virtual\n returns (bool)\n {}\n\n function isPaymentLate(uint256 _bidId) public view returns (bool) {}\n\n function getLoanBorrower(uint256 _bidId)\n external\n view\n virtual\n returns (address borrower_)\n {\n borrower_ = bids[_bidId].borrower;\n }\n\n function getLoanLender(uint256 _bidId)\n external\n view\n virtual\n returns (address lender_)\n {\n lender_ = bids[_bidId].lender;\n }\n\n function getLoanMarketId(uint256 _bidId)\n external\n view\n returns (uint256 _marketId)\n {\n _marketId = bids[_bidId].marketplaceId;\n }\n\n function getLoanLendingToken(uint256 _bidId)\n external\n view\n returns (address token_)\n {\n token_ = address(bids[_bidId].loanDetails.lendingToken);\n }\n\n function getLoanSummary(uint256 _bidId)\n external\n view\n returns (\n address borrower,\n address lender,\n uint256 marketId,\n address principalTokenAddress,\n uint256 principalAmount,\n uint32 acceptedTimestamp,\n uint32 lastRepaidTimestamp,\n BidState bidState\n )\n {\n Bid storage bid = bids[_bidId];\n\n borrower = bid.borrower;\n lender = bid.lender;\n marketId = bid.marketplaceId;\n principalTokenAddress = address(bid.loanDetails.lendingToken);\n principalAmount = bid.loanDetails.principal;\n acceptedTimestamp = bid.loanDetails.acceptedTimestamp;\n lastRepaidTimestamp = bid.loanDetails.lastRepaidTimestamp;\n bidState = bid.state;\n }\n\n function setLastRepaidTimestamp(uint256 _bidId, uint32 _timestamp) public {\n bids[_bidId].loanDetails.lastRepaidTimestamp = _timestamp;\n }\n\n\n\n function mock_setLoanDefaultTimestamp(\n uint256 _defaultedAt\n ) external returns (uint256){\n mockLoanDefaultTimestamp = _defaultedAt;\n } \n\n\n\n function getRepaymentListenerForBid(uint256 _bidId)\n public\n view\n returns (address)\n {}\n\n function setRepaymentListenerForBid(uint256 _bidId, address _listener)\n public\n {}\n\n\n function _getBidPaymentCycleType(uint256 _bidId)\n internal\n view\n returns (PaymentCycleType)\n {\n /* bytes32 bidTermsId = bidMarketTermsId[_bidId];\n if (bidTermsId != bytes32(0)) {\n return marketRegistry.getPaymentCycleTypeForTerms(bidTermsId);\n }*/\n\n return globalBidPaymentCycleType;\n }\n\n function _getBidPaymentCycleDuration(uint256 _bidId)\n internal\n view\n returns (uint32)\n {\n /* bytes32 bidTermsId = bidMarketTermsId[_bidId];\n if (bidTermsId != bytes32(0)) {\n return marketRegistry.getPaymentCycleDurationForTerms(bidTermsId);\n }*/\n\n Bid storage bid = bids[_bidId];\n\n return globalBidPaymentCycleDuration;\n }\n}\n" + }, + "contracts/mock/uniswap/UniswapV3FactoryMock.sol": { + "content": "contract UniswapV3FactoryMock {\n address poolMock;\n\n function getPool(address token0, address token1, uint24 fee)\n public\n returns (address)\n {\n return poolMock;\n }\n\n function setPoolMock(address _pool) public {\n poolMock = _pool;\n }\n}\n" + }, + "contracts/mock/uniswap/UniswapV3PoolMock.sol": { + "content": "\ncontract UniswapV3PoolMock {\n //this represents an equal price ratio\n uint160 mockSqrtPriceX96 = 2 ** 96;\n\n address mockToken0;\n address mockToken1;\n\n\n \n\n struct Slot0 {\n // the current price\n uint160 sqrtPriceX96;\n // the current tick\n int24 tick;\n // the most-recently updated index of the observations array\n uint16 observationIndex;\n // the current maximum number of observations that are being stored\n uint16 observationCardinality;\n // the next maximum number of observations to store, triggered in observations.write\n uint16 observationCardinalityNext;\n // the current protocol fee as a percentage of the swap fee taken on withdrawal\n // represented as an integer denominator (1/x)%\n uint8 feeProtocol;\n // whether the pool is locked\n bool unlocked;\n }\n\n function set_mockSqrtPriceX96(uint160 _price) public {\n mockSqrtPriceX96 = _price;\n }\n\n function set_mockToken0(address t0) public {\n mockToken0 = t0;\n }\n\n\n function set_mockToken1(address t1) public {\n mockToken1 = t1;\n }\n\n function token0() public returns (address) {\n return mockToken0;\n }\n\n function token1() public returns (address) {\n return mockToken1;\n }\n\n\n function slot0() public returns (Slot0 memory slot0) {\n return\n Slot0({\n sqrtPriceX96: mockSqrtPriceX96,\n tick: 0,\n observationIndex: 0,\n observationCardinality: 0,\n observationCardinalityNext: 0,\n feeProtocol: 0,\n unlocked: true\n });\n }\n\n //mock fn \n function observe(uint32[] calldata secondsAgos)\n external\n view\n returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s)\n {\n // Initialize the return arrays\n tickCumulatives = new int56[](secondsAgos.length);\n secondsPerLiquidityCumulativeX128s = new uint160[](secondsAgos.length);\n\n // Mock data generation - replace this with your logic or static values\n for (uint256 i = 0; i < secondsAgos.length; i++) {\n // Generate mock data. Here we're just using simple static values for demonstration.\n // You should replace these with dynamic values based on your testing needs.\n tickCumulatives[i] = int56(1000 * int256(i)); // Example mock data\n secondsPerLiquidityCumulativeX128s[i] = uint160(2000 * i); // Example mock data\n }\n\n return (tickCumulatives, secondsPerLiquidityCumulativeX128s);\n }\n \n \n\n}" + }, + "contracts/mock/WethMock.sol": { + "content": "/**\n *Submitted for verification at Etherscan.io on 2017-12-12\n */\n\n// Copyright (C) 2015, 2016, 2017 Dapphub\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity ^0.8.0;\n\n// SPDX-License-Identifier: MIT\n\ncontract WethMock {\n string public name = \"Wrapped Ether\";\n string public symbol = \"WETH\";\n uint8 public decimals = 18;\n\n event Approval(address indexed src, address indexed guy, uint256 wad);\n event Transfer(address indexed src, address indexed dst, uint256 wad);\n event Deposit(address indexed dst, uint256 wad);\n event Withdrawal(address indexed src, uint256 wad);\n\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n function deposit() public payable {\n balanceOf[msg.sender] += msg.value;\n emit Deposit(msg.sender, msg.value);\n }\n\n function withdraw(uint256 wad) public {\n require(balanceOf[msg.sender] >= wad);\n balanceOf[msg.sender] -= wad;\n payable(msg.sender).transfer(wad);\n emit Withdrawal(msg.sender, wad);\n }\n\n function totalSupply() public view returns (uint256) {\n return address(this).balance;\n }\n\n function approve(address guy, uint256 wad) public returns (bool) {\n allowance[msg.sender][guy] = wad;\n emit Approval(msg.sender, guy, wad);\n return true;\n }\n\n function transfer(address dst, uint256 wad) public returns (bool) {\n return transferFrom(msg.sender, dst, wad);\n }\n\n function transferFrom(address src, address dst, uint256 wad)\n public\n returns (bool)\n {\n require(balanceOf[src] >= wad, \"insufficient balance\");\n\n if (src != msg.sender) {\n require(\n allowance[src][msg.sender] >= wad,\n \"insufficient allowance\"\n );\n allowance[src][msg.sender] -= wad;\n }\n\n balanceOf[src] -= wad;\n balanceOf[dst] += wad;\n\n emit Transfer(src, dst, wad);\n\n return true;\n }\n\n\n \n}\n" + }, + "contracts/openzeppelin/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)\npragma solidity ^0.8.0;\n\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {UpgradeableBeacon} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}" + }, + "contracts/openzeppelin/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol)\npragma solidity ^0.8.0;\n\n\nimport {Proxy} from \"../Proxy.sol\";\nimport {ERC1967Utils} from \"./ERC1967Utils.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an\n * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.\n *\n * Requirements:\n *\n * - If `data` is empty, `msg.value` must be zero.\n */\n constructor(address implementation, bytes memory _data) payable {\n ERC1967Utils.upgradeToAndCall(implementation, _data);\n }\n\n /**\n * @dev Returns the current implementation address.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function _implementation() internal view virtual override returns (address) {\n return ERC1967Utils.getImplementation();\n }\n}" + }, + "contracts/openzeppelin/ERC1967/ERC1967Utils.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)\npragma solidity ^0.8.0;\n\n\nimport {IBeacon} from \"../beacon/IBeacon.sol\";\nimport {Address} from \"../utils/Address.sol\";\nimport {StorageSlot} from \"../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.\n */\nlibrary ERC1967Utils {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev The `implementation` of the proxy is invalid.\n */\n error ERC1967InvalidImplementation(address implementation);\n\n /**\n * @dev The `admin` of the proxy is invalid.\n */\n error ERC1967InvalidAdmin(address admin);\n\n /**\n * @dev The `beacon` of the proxy is invalid.\n */\n error ERC1967InvalidBeacon(address beacon);\n\n /**\n * @dev An upgrade function sees `msg.value > 0` that may be lost.\n */\n error ERC1967NonPayable();\n\n /**\n * @dev Returns the current implementation address.\n */\n function getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the ERC-1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n if (newImplementation.code.length == 0) {\n revert ERC1967InvalidImplementation(newImplementation);\n }\n StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Performs implementation upgrade with additional setup call if data is nonempty.\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n * to avoid stuck value in the contract.\n *\n * Emits an {IERC1967-Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n\n if (data.length > 0) {\n Address.functionDelegateCall(newImplementation, data);\n } else {\n _checkNonPayable();\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using\n * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the ERC-1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n if (newAdmin == address(0)) {\n revert ERC1967InvalidAdmin(address(0));\n }\n StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {IERC1967-AdminChanged} event.\n */\n function changeAdmin(address newAdmin) internal {\n emit AdminChanged(getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is the keccak-256 hash of \"eip1967.proxy.beacon\" subtracted by 1.\n */\n // solhint-disable-next-line private-vars-leading-underscore\n bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the ERC-1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n if (newBeacon.code.length == 0) {\n revert ERC1967InvalidBeacon(newBeacon);\n }\n\n StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;\n\n address beaconImplementation = IBeacon(newBeacon).implementation();\n if (beaconImplementation.code.length == 0) {\n revert ERC1967InvalidImplementation(beaconImplementation);\n }\n }\n\n /**\n * @dev Change the beacon and trigger a setup call if data is nonempty.\n * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected\n * to avoid stuck value in the contract.\n *\n * Emits an {IERC1967-BeaconUpgraded} event.\n *\n * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since\n * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for\n * efficiency.\n */\n function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n\n if (data.length > 0) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n } else {\n _checkNonPayable();\n }\n }\n\n /**\n * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract\n * if an upgrade doesn't perform an initialization call.\n */\n function _checkNonPayable() private {\n if (msg.value > 0) {\n revert ERC1967NonPayable();\n }\n }\n}" + }, + "contracts/openzeppelin/ERC1967/IERC1967.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)\npragma solidity ^0.8.0;\n\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}" + }, + "contracts/openzeppelin/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\npragma solidity ^0.8.0;\n\n\nimport {Context} from \"./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 * The initial owner is set to the address provided by the deployer. This can\n * 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 /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n constructor(address initialOwner) {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling 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 if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\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}" + }, + "contracts/openzeppelin/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)\npragma solidity ^0.8.0;\n\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback\n * function and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n}" + }, + "contracts/openzeppelin/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport {ITransparentUpgradeableProxy} from \"./TransparentUpgradeableProxy.sol\";\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n /**\n * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgrade(address)`\n * and `upgradeAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,\n * while `upgradeAndCall` will invoke the `receive` function if the second argument is the empty byte string.\n * If the getter returns `\"5.0.0\"`, only `upgradeAndCall(address,bytes)` is present, and the second argument must\n * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function\n * during an upgrade.\n */\n string public constant UPGRADE_INTERFACE_VERSION = \"5.0.0\";\n\n /**\n * @dev Sets the initial owner who can perform upgrades.\n */\n constructor(address initialOwner) Ownable(initialOwner) {}\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation.\n * See {TransparentUpgradeableProxy-_dispatchUpgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n * - If `data` is empty, `msg.value` must be zero.\n */\n function upgradeAndCall(\n ITransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}" + }, + "contracts/openzeppelin/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport {ERC1967Utils} from \"./ERC1967/ERC1967Utils.sol\";\nimport {ERC1967Proxy} from \"./ERC1967/ERC1967Proxy.sol\";\nimport {IERC1967} from \"./ERC1967/IERC1967.sol\";\nimport {ProxyAdmin} from \"./ProxyAdmin.sol\";\n\n/**\n * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}\n * does not implement this interface directly, and its upgradeability mechanism is implemented by an internal dispatch\n * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not\n * include them in the ABI so this interface must be used to interact with it.\n */\ninterface ITransparentUpgradeableProxy is IERC1967 {\n function upgradeToAndCall(address, bytes calldata) external payable;\n}\n\n/**\n * @dev This contract implements a proxy that is upgradeable through an associated {ProxyAdmin} instance.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches the {ITransparentUpgradeableProxy-upgradeToAndCall} function exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can call the `upgradeToAndCall` function but any other call won't be forwarded to\n * the implementation. If the admin tries to call a function on the implementation it will fail with an error indicating\n * the proxy admin cannot fallback to the target implementation.\n *\n * These properties mean that the admin account can only be used for upgrading the proxy, so it's best if it's a\n * dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to\n * call a function from the proxy implementation. For this reason, the proxy deploys an instance of {ProxyAdmin} and\n * allows upgrades only if they come through it. You should think of the `ProxyAdmin` instance as the administrative\n * interface of the proxy, including the ability to change who can trigger upgrades by transferring ownership.\n *\n * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not\n * inherit from that interface, and instead `upgradeToAndCall` is implicitly implemented using a custom dispatch\n * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to\n * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the\n * implementation.\n *\n * NOTE: This proxy does not inherit from {Context} deliberately. The {ProxyAdmin} of this contract won't send a\n * meta-transaction in any way, and any other meta-transaction setup should be made in the implementation contract.\n *\n * IMPORTANT: This contract avoids unnecessary storage reads by setting the admin only during construction as an\n * immutable variable, preventing any changes thereafter. However, the admin slot defined in ERC-1967 can still be\n * overwritten by the implementation logic pointed to by this proxy. In such cases, the contract may end up in an\n * undesirable state where the admin slot is different from the actual admin. Relying on the value of the admin slot\n * is generally fine if the implementation is trusted.\n *\n * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the\n * compiler will not check that there are no selector conflicts, due to the note above. A selector clash between any new\n * function and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This\n * could render the `upgradeToAndCall` function inaccessible, preventing upgradeability and compromising transparency.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n // An immutable address for the admin to avoid unnecessary SLOADs before each call\n // at the expense of removing the ability to change the admin once it's set.\n // This is acceptable if the admin is always a ProxyAdmin instance or similar contract\n // with its own ability to transfer the permissions to another account.\n address private immutable _admin;\n\n /**\n * @dev The proxy caller is the current admin, and can't fallback to the proxy target.\n */\n error ProxyDeniedAdminAccess();\n\n /**\n * @dev Initializes an upgradeable proxy managed by an instance of a {ProxyAdmin} with an `initialOwner`,\n * backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in\n * {ERC1967Proxy-constructor}.\n */\n constructor(address _logic, address initialOwner, bytes memory _data) payable ERC1967Proxy(_logic, _data) {\n _admin = address(new ProxyAdmin(initialOwner));\n // Set the storage value and emit an event for ERC-1967 compatibility\n ERC1967Utils.changeAdmin(_proxyAdmin());\n }\n\n /**\n * @dev Returns the admin of this proxy.\n */\n function _proxyAdmin() internal view virtual returns (address) {\n return _admin;\n }\n\n /**\n * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior.\n */\n function _fallback() internal virtual override {\n if (msg.sender == _proxyAdmin()) {\n if (msg.sig != ITransparentUpgradeableProxy.upgradeToAndCall.selector) {\n revert ProxyDeniedAdminAccess();\n } else {\n _dispatchUpgradeToAndCall();\n }\n } else {\n super._fallback();\n }\n }\n\n /**\n * @dev Upgrade the implementation of the proxy. See {ERC1967Utils-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - If `data` is empty, `msg.value` must be zero.\n */\n function _dispatchUpgradeToAndCall() private {\n (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));\n ERC1967Utils.upgradeToAndCall(newImplementation, data);\n }\n}" + }, + "contracts/openzeppelin/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)\npragma solidity ^0.8.0;\n\n\nimport {Errors} from \"./Errors.sol\";\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev There's no code at `target` (it is not a contract).\n */\n error AddressEmptyCode(address target);\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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n if (address(this).balance < amount) {\n revert Errors.InsufficientBalance(address(this).balance, amount);\n }\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n if (!success) {\n revert Errors.FailedCall();\n }\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 or custom error, it is bubbled\n * up by this function (like regular Solidity function calls). However, if\n * the call reverted with no returned reason, this function reverts with a\n * {Errors.FailedCall} error.\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 function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0);\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 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n if (address(this).balance < value) {\n revert Errors.InsufficientBalance(address(this).balance, value);\n }\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target\n * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case\n * of an unsuccessful call.\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata\n ) internal view returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n // only check if target is a contract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n if (returndata.length == 0 && target.code.length == 0) {\n revert AddressEmptyCode(target);\n }\n return returndata;\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the\n * revert reason or with a default {Errors.FailedCall} error.\n */\n function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {\n if (!success) {\n _revert(returndata);\n } else {\n return returndata;\n }\n }\n\n /**\n * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.\n */\n function _revert(bytes memory returndata) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert Errors.FailedCall();\n }\n }\n}" + }, + "contracts/openzeppelin/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\npragma solidity ^0.8.0;\n\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 function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}" + }, + "contracts/openzeppelin/utils/Errors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\n/**\n * @dev Collection of common custom errors used in multiple contracts\n *\n * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.\n * It is recommended to avoid relying on the error API for critical functionality.\n */\nlibrary Errors {\n /**\n * @dev The ETH balance of the account is not enough to perform the operation.\n */\n error InsufficientBalance(uint256 balance, uint256 needed);\n\n /**\n * @dev A call to an address target failed. The target may have reverted.\n */\n error FailedCall();\n\n /**\n * @dev The deployment failed.\n */\n error FailedDeployment();\n}" + }, + "contracts/openzeppelin/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC-1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(newImplementation.code.length > 0);\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}" + }, + "contracts/pausing/HasProtocolPausingManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\n \n \n//import \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n \n\nimport \"../interfaces/IHasProtocolPausingManager.sol\";\n\nimport \"../interfaces/IProtocolPausingManager.sol\";\n \n\nabstract contract HasProtocolPausingManager \n is \n IHasProtocolPausingManager \n {\n \n\n bool private _reserved0;// _paused.. Deprecated , handled by pausing manager \n\n address private _protocolPausingManager;\n \n\n modifier whenLiquidationsNotPaused() {\n require(! IProtocolPausingManager(_protocolPausingManager). liquidationsPaused(), \"Liquidations paused\" );\n \n _;\n }\n\n //rename to when protocol not paused ?\n modifier whenProtocolNotPaused() {\n require(! IProtocolPausingManager(_protocolPausingManager). protocolPaused(), \"Protocol paused\" );\n \n _;\n }\n \n\n //onlyinitializing? \n function _setProtocolPausingManager(address protocolPausingManager) internal {\n _protocolPausingManager = protocolPausingManager ;\n }\n\n\n function getProtocolPausingManager() public view returns (address){\n\n return _protocolPausingManager;\n }\n\n \n /* \n function isPauser(address _address) public view returns (bool){\n\n return IProtocolPausingManager(_protocolPausingManager). isPauser(_address) ;\n }\n\n function getLastUnpausedAt() \n external view \n returns (uint256) {\n\n return IPausableTimestamp(_protocolPausingManager).getLastUnpausedAt();\n\n } \n */\n\n \n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[48] private __gap;\n}\n" + }, + "contracts/pausing/ProtocolPausingManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\n\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n\n\nimport \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\n\n\n\nimport \"../interfaces/IProtocolPausingManager.sol\";\n\n\nimport \"../interfaces/IPausableTimestamp.sol\";\n\n/**\n \n TODO:\n\n Move SCF pausing into here ??\n\n\n */\ncontract ProtocolPausingManager is ContextUpgradeable, OwnableUpgradeable, IProtocolPausingManager , IPausableTimestamp{\n using MathUpgradeable for uint256;\n\n bool private _protocolPaused; \n bool private _liquidationsPaused; \n //bool private _liquidityPoolsPaused; \n\n\n // u8 private _currentPauseState; //use an enum !!! \n\n mapping(address => bool) public pauserRoleBearer ;\n\n\n uint256 private lastPausedAt;\n uint256 private lastUnpausedAt;\n\n\n // Events\n event PausedProtocol(address indexed account);\n event UnpausedProtocol(address indexed account);\n event PausedLiquidations(address indexed account);\n event UnpausedLiquidations(address indexed account);\n event PauserAdded(address indexed account);\n event PauserRemoved(address indexed account);\n \n \n modifier onlyPauser() {\n require( isPauser( _msgSender()) );\n _;\n }\n\n\n //need to initialize so owner is owner (transfer ownership to safe)\n\n function initialize(\n \n ) external initializer {\n\n __Ownable_init();\n\n }\n \n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function protocolPaused() public view virtual returns (bool) {\n return _protocolPaused;\n }\n\n\n function liquidationsPaused() public view virtual returns (bool) {\n return _liquidationsPaused;\n }\n\n \n /*\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n */\n \n\n\n\n\n function pauseProtocol() public virtual onlyPauser {\n require( _protocolPaused == false);\n _protocolPaused = true;\n lastPausedAt = block.timestamp;\n emit PausedProtocol(_msgSender());\n }\n\n \n function unpauseProtocol() public virtual onlyPauser {\n \n require( _protocolPaused == true);\n _protocolPaused = false;\n lastUnpausedAt = block.timestamp;\n emit UnpausedProtocol(_msgSender());\n }\n\n function pauseLiquidations() public virtual onlyPauser {\n \n require( _liquidationsPaused == false);\n _liquidationsPaused = true;\n lastPausedAt = block.timestamp;\n emit PausedLiquidations(_msgSender());\n }\n\n \n function unpauseLiquidations() public virtual onlyPauser {\n require( _liquidationsPaused == true);\n _liquidationsPaused = false;\n lastUnpausedAt = block.timestamp;\n emit UnpausedLiquidations(_msgSender());\n }\n\n function getLastPausedAt() \n external view \n returns (uint256) {\n\n return lastPausedAt;\n\n } \n\n\n function getLastUnpausedAt() \n external view \n returns (uint256) {\n\n return lastUnpausedAt;\n\n } \n\n\n\n\n // Role Management \n\n\n function addPauser(address _pauser) public virtual onlyOwner {\n pauserRoleBearer[_pauser] = true;\n emit PauserAdded(_pauser);\n }\n\n\n function removePauser(address _pauser) public virtual onlyOwner {\n pauserRoleBearer[_pauser] = false;\n emit PauserRemoved(_pauser);\n }\n\n\n function isPauser(address _account) public view returns(bool){\n return pauserRoleBearer[_account] || _account == owner() ;\n }\n\n \n}\n" + }, + "contracts/ProtocolFee.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract ProtocolFee is OwnableUpgradeable {\n // Protocol fee set for loan processing.\n uint16 private _protocolFee;\n\n /**\n * @notice This event is emitted when the protocol fee has been updated.\n * @param newFee The new protocol fee set.\n * @param oldFee The previously set protocol fee.\n */\n event ProtocolFeeSet(uint16 newFee, uint16 oldFee);\n\n /**\n * @notice Initialized the protocol fee.\n * @param initFee The initial protocol fee to be set on the protocol.\n */\n function __ProtocolFee_init(uint16 initFee) internal onlyInitializing {\n __Ownable_init();\n __ProtocolFee_init_unchained(initFee);\n }\n\n function __ProtocolFee_init_unchained(uint16 initFee)\n internal\n onlyInitializing\n {\n setProtocolFee(initFee);\n }\n\n /**\n * @notice Returns the current protocol fee.\n */\n function protocolFee() public view virtual returns (uint16) {\n return _protocolFee;\n }\n\n /**\n * @notice Lets the DAO/owner of the protocol to set a new protocol fee.\n * @param newFee The new protocol fee to be set.\n */\n function setProtocolFee(uint16 newFee) public virtual onlyOwner {\n // Skip if the fee is the same\n if (newFee == _protocolFee) return;\n\n uint16 oldFee = _protocolFee;\n _protocolFee = newFee;\n emit ProtocolFeeSet(newFee, oldFee);\n }\n}\n" + }, + "contracts/ProtocolFeeMock.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./ProtocolFee.sol\";\n\ncontract ProtocolFeeMock is ProtocolFee {\n bool public setProtocolFeeCalled;\n\n function initialize(uint16 _initFee) external initializer {\n __ProtocolFee_init(_initFee);\n }\n\n function setProtocolFee(uint16 newFee) public override onlyOwner {\n setProtocolFeeCalled = true;\n\n bool _isInitializing;\n assembly {\n _isInitializing := sload(1)\n }\n\n // Only call the actual function if we are not initializing\n if (!_isInitializing) {\n super.setProtocolFee(newFee);\n }\n }\n}\n" + }, + "contracts/ReputationManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\n// Interfaces\nimport \"./interfaces/IReputationManager.sol\";\nimport \"./interfaces/ITellerV2.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n// Libraries\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\n\ncontract ReputationManager is IReputationManager, Initializable {\n using EnumerableSet for EnumerableSet.UintSet;\n\n bytes32 public constant CONTROLLER = keccak256(\"CONTROLLER\");\n\n ITellerV2 public tellerV2;\n mapping(address => EnumerableSet.UintSet) private _delinquencies;\n mapping(address => EnumerableSet.UintSet) private _defaults;\n mapping(address => EnumerableSet.UintSet) private _currentDelinquencies;\n mapping(address => EnumerableSet.UintSet) private _currentDefaults;\n\n event MarkAdded(\n address indexed account,\n RepMark indexed repMark,\n uint256 bidId\n );\n event MarkRemoved(\n address indexed account,\n RepMark indexed repMark,\n uint256 bidId\n );\n\n /**\n * @notice Initializes the proxy.\n */\n function initialize(address _tellerV2) external initializer {\n tellerV2 = ITellerV2(_tellerV2);\n }\n\n function getDelinquentLoanIds(address _account)\n public\n override\n returns (uint256[] memory)\n {\n updateAccountReputation(_account);\n return _delinquencies[_account].values();\n }\n\n function getDefaultedLoanIds(address _account)\n public\n override\n returns (uint256[] memory)\n {\n updateAccountReputation(_account);\n return _defaults[_account].values();\n }\n\n function getCurrentDelinquentLoanIds(address _account)\n public\n override\n returns (uint256[] memory)\n {\n updateAccountReputation(_account);\n return _currentDelinquencies[_account].values();\n }\n\n function getCurrentDefaultLoanIds(address _account)\n public\n override\n returns (uint256[] memory)\n {\n updateAccountReputation(_account);\n return _currentDefaults[_account].values();\n }\n\n function updateAccountReputation(address _account) public override {\n uint256[] memory activeBidIds = tellerV2.getBorrowerActiveLoanIds(\n _account\n );\n for (uint256 i; i < activeBidIds.length; i++) {\n _applyReputation(_account, activeBidIds[i]);\n }\n }\n\n function updateAccountReputation(address _account, uint256 _bidId)\n public\n override\n returns (RepMark)\n {\n return _applyReputation(_account, _bidId);\n }\n\n function _applyReputation(address _account, uint256 _bidId)\n internal\n returns (RepMark mark_)\n {\n mark_ = RepMark.Good;\n\n if (tellerV2.isLoanDefaulted(_bidId)) {\n mark_ = RepMark.Default;\n\n // Remove delinquent status\n _removeMark(_account, _bidId, RepMark.Delinquent);\n } else if (tellerV2.isPaymentLate(_bidId)) {\n mark_ = RepMark.Delinquent;\n }\n\n // Mark status if not \"Good\"\n if (mark_ != RepMark.Good) {\n _addMark(_account, _bidId, mark_);\n }\n }\n\n function _addMark(address _account, uint256 _bidId, RepMark _mark)\n internal\n {\n if (_mark == RepMark.Delinquent) {\n _delinquencies[_account].add(_bidId);\n _currentDelinquencies[_account].add(_bidId);\n } else if (_mark == RepMark.Default) {\n _defaults[_account].add(_bidId);\n _currentDefaults[_account].add(_bidId);\n }\n\n emit MarkAdded(_account, _mark, _bidId);\n }\n\n function _removeMark(address _account, uint256 _bidId, RepMark _mark)\n internal\n {\n if (_mark == RepMark.Delinquent) {\n _currentDelinquencies[_account].remove(_bidId);\n } else if (_mark == RepMark.Default) {\n _currentDefaults[_account].remove(_bidId);\n }\n\n emit MarkRemoved(_account, _mark, _bidId);\n }\n}\n" + }, + "contracts/TellerV0Storage.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/*\n\n THIS IS ONLY USED FOR SUBGRAPH \n \n\n*/\n\ncontract TellerV0Storage {\n enum BidState {\n NONEXISTENT,\n PENDING,\n CANCELLED,\n ACCEPTED,\n PAID,\n LIQUIDATED,\n CLOSED\n }\n\n /**\n * @notice Represents a total amount for a payment.\n * @param principal Amount that counts towards the principal.\n * @param interest Amount that counts toward interest.\n */\n struct Payment {\n uint256 principal;\n uint256 interest;\n }\n\n /**\n * @notice Details about the loan.\n * @param lendingToken The token address for the loan.\n * @param principal The amount of tokens initially lent out.\n * @param totalRepaid Payment struct that represents the total principal and interest amount repaid.\n * @param timestamp Timestamp, in seconds, of when the bid was submitted by the borrower.\n * @param acceptedTimestamp Timestamp, in seconds, of when the bid was accepted by the lender.\n * @param lastRepaidTimestamp Timestamp, in seconds, of when the last payment was made\n * @param loanDuration The duration of the loan.\n */\n struct LoanDetails {\n ERC20 lendingToken;\n uint256 principal;\n Payment totalRepaid;\n uint32 timestamp;\n uint32 acceptedTimestamp;\n uint32 lastRepaidTimestamp;\n uint32 loanDuration;\n }\n\n /**\n * @notice Details about a loan request.\n * @param borrower Account address who is requesting a loan.\n * @param receiver Account address who will receive the loan amount.\n * @param lender Account address who accepted and funded the loan request.\n * @param marketplaceId ID of the marketplace the bid was submitted to.\n * @param metadataURI ID of off chain metadata to find additional information of the loan request.\n * @param loanDetails Struct of the specific loan details.\n * @param terms Struct of the loan request terms.\n * @param state Represents the current state of the loan.\n */\n struct Bid0 {\n address borrower;\n address receiver;\n address _lender; // DEPRECATED\n uint256 marketplaceId;\n bytes32 _metadataURI; // DEPRECATED\n LoanDetails loanDetails;\n Terms terms;\n BidState state;\n }\n\n /**\n * @notice Information on the terms of a loan request\n * @param paymentCycleAmount Value of tokens expected to be repaid every payment cycle.\n * @param paymentCycle Duration, in seconds, of how often a payment must be made.\n * @param APR Annual percentage rating to be applied on repayments. (10000 == 100%)\n */\n struct Terms {\n uint256 paymentCycleAmount;\n uint32 paymentCycle;\n uint16 APR;\n }\n\n // Mapping of bidId to bid information.\n mapping(uint256 => Bid0) public bids;\n}\n" + }, + "contracts/TellerV2.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"./ProtocolFee.sol\";\nimport \"./TellerV2Storage.sol\";\nimport \"./TellerV2Context.sol\";\nimport \"./pausing/HasProtocolPausingManager.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\"; \nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\";\n\n// Interfaces\nimport \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/IReputationManager.sol\";\nimport \"./interfaces/ITellerV2.sol\";\nimport { Collateral } from \"./interfaces/escrow/ICollateralEscrowV1.sol\";\nimport \"./interfaces/IEscrowVault.sol\";\n\nimport { ILoanRepaymentCallbacks } from \"./interfaces/ILoanRepaymentCallbacks.sol\";\nimport \"./interfaces/ILoanRepaymentListener.sol\";\n\n// Libraries\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"./libraries/NumbersLib.sol\";\n\nimport { V2Calculations, PaymentCycleType } from \"./libraries/V2Calculations.sol\";\n\n/* Errors */\n/**\n * @notice This error is reverted when the action isn't allowed\n * @param bidId The id of the bid.\n * @param action The action string (i.e: 'repayLoan', 'cancelBid', 'etc)\n * @param message The message string to return to the user explaining why the tx was reverted\n */\nerror ActionNotAllowed(uint256 bidId, string action, string message);\n\n/**\n * @notice This error is reverted when repayment amount is less than the required minimum\n * @param bidId The id of the bid the borrower is attempting to repay.\n * @param payment The payment made by the borrower\n * @param minimumOwed The minimum owed value\n */\nerror PaymentNotMinimum(uint256 bidId, uint256 payment, uint256 minimumOwed);\n\ncontract TellerV2 is\n ITellerV2,\n ILoanRepaymentCallbacks,\n OwnableUpgradeable,\n ProtocolFee,\n HasProtocolPausingManager,\n TellerV2Storage,\n TellerV2Context\n{\n using Address for address;\n using SafeERC20 for IERC20;\n using NumbersLib for uint256;\n using EnumerableSet for EnumerableSet.AddressSet;\n using EnumerableSet for EnumerableSet.UintSet;\n\n //the first 20 bytes of keccak256(\"lender manager\")\n address constant USING_LENDER_MANAGER =\n 0x84D409EeD89F6558fE3646397146232665788bF8;\n\n /** Events */\n\n /**\n * @notice This event is emitted when a new bid is submitted.\n * @param bidId The id of the bid submitted.\n * @param borrower The address of the bid borrower.\n * @param metadataURI URI for additional bid information as part of loan bid.\n */\n event SubmittedBid(\n uint256 indexed bidId,\n address indexed borrower,\n address receiver,\n bytes32 indexed metadataURI\n );\n\n /**\n * @notice This event is emitted when a bid has been accepted by a lender.\n * @param bidId The id of the bid accepted.\n * @param lender The address of the accepted bid lender.\n */\n event AcceptedBid(uint256 indexed bidId, address indexed lender);\n\n /**\n * @notice This event is emitted when a previously submitted bid has been cancelled.\n * @param bidId The id of the cancelled bid.\n */\n event CancelledBid(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when market owner has cancelled a pending bid in their market.\n * @param bidId The id of the bid funded.\n *\n * Note: The `CancelledBid` event will also be emitted.\n */\n event MarketOwnerCancelledBid(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when a payment is made towards an active loan.\n * @param bidId The id of the bid/loan to which the payment was made.\n */\n event LoanRepayment(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when a loan has been fully repaid.\n * @param bidId The id of the bid/loan which was repaid.\n */\n event LoanRepaid(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when a loan has been closed by a lender to claim collateral.\n * @param bidId The id of the bid accepted.\n */\n event LoanClosed(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when a loan has been fully repaid.\n * @param bidId The id of the bid/loan which was repaid.\n */\n event LoanLiquidated(uint256 indexed bidId, address indexed liquidator);\n\n /**\n * @notice This event is emitted when a fee has been paid related to a bid.\n * @param bidId The id of the bid.\n * @param feeType The name of the fee being paid.\n * @param amount The amount of the fee being paid.\n */\n event FeePaid(\n uint256 indexed bidId,\n string indexed feeType,\n uint256 indexed amount\n );\n\n /** Modifiers */\n\n /**\n * @notice This modifier is used to check if the state of a bid is pending, before running an action.\n * @param _bidId The id of the bid to check the state for.\n * @param _action The desired action to run on the bid.\n */\n modifier pendingBid(uint256 _bidId, string memory _action) {\n if (bids[_bidId].state != BidState.PENDING) {\n revert ActionNotAllowed(_bidId, _action, \"Bid not pending\");\n }\n\n _;\n }\n\n /**\n * @notice This modifier is used to check if the state of a loan has been accepted, before running an action.\n * @param _bidId The id of the bid to check the state for.\n * @param _action The desired action to run on the bid.\n */\n modifier acceptedLoan(uint256 _bidId, string memory _action) {\n if (bids[_bidId].state != BidState.ACCEPTED) {\n revert ActionNotAllowed(_bidId, _action, \"Loan not accepted\");\n }\n\n _;\n }\n\n\n /** Constant Variables **/\n\n uint8 public constant CURRENT_CODE_VERSION = 10;\n\n uint32 public constant LIQUIDATION_DELAY = 86400; //ONE DAY IN SECONDS\n\n /** Constructor **/\n\n constructor(address trustedForwarder) TellerV2Context(trustedForwarder) {}\n\n /** External Functions **/\n\n /**\n * @notice Initializes the proxy.\n * @param _protocolFee The fee collected by the protocol for loan processing.\n * @param _marketRegistry The address of the market registry contract for the protocol.\n * @param _reputationManager The address of the reputation manager contract.\n * @param _lenderCommitmentForwarder The address of the lender commitment forwarder contract.\n * @param _collateralManager The address of the collateral manager contracts.\n * @param _lenderManager The address of the lender manager contract for loans on the protocol.\n * @param _protocolPausingManager The address of the pausing manager contract for the protocol.\n */\n function initialize(\n uint16 _protocolFee,\n address _marketRegistry,\n address _reputationManager,\n address _lenderCommitmentForwarder,\n address _collateralManager,\n address _lenderManager,\n address _escrowVault,\n address _protocolPausingManager\n ) external initializer {\n __ProtocolFee_init(_protocolFee);\n\n //__Pausable_init();\n\n require(\n _lenderCommitmentForwarder.isContract(),\n \"LCF_ic\"\n );\n lenderCommitmentForwarder = _lenderCommitmentForwarder;\n\n require(\n _marketRegistry.isContract(),\n \"MR_ic\"\n );\n marketRegistry = IMarketRegistry(_marketRegistry);\n\n require(\n _reputationManager.isContract(),\n \"RM_ic\"\n );\n reputationManager = IReputationManager(_reputationManager);\n\n require(\n _collateralManager.isContract(),\n \"CM_ic\"\n );\n collateralManager = ICollateralManager(_collateralManager);\n\n \n \n require(\n _lenderManager.isContract(),\n \"LM_ic\"\n );\n lenderManager = ILenderManager(_lenderManager);\n\n\n \n\n require(_escrowVault.isContract(), \"EV_ic\");\n escrowVault = IEscrowVault(_escrowVault);\n\n\n\n\n _setProtocolPausingManager(_protocolPausingManager);\n }\n\n\n /* function setEscrowVault(address _escrowVault) external reinitializer(9) {\n _setEscrowVault(_escrowVault);\n }\n */\n\n\n function setProtocolPausingManager( \n address _protocolPausingManager\n ) external onlyOwner reinitializer(10) {\n\n _setProtocolPausingManager(_protocolPausingManager);\n\n }\n \n \n /**\n * @notice Function for a borrower to create a bid for a loan without Collateral.\n * @param _lendingToken The lending token asset requested to be borrowed.\n * @param _marketplaceId The unique id of the marketplace for the bid.\n * @param _principal The principal amount of the loan bid.\n * @param _duration The recurrent length of time before which a payment is due.\n * @param _APR The proposed interest rate for the loan bid.\n * @param _metadataURI The URI for additional borrower loan information as part of loan bid.\n * @param _receiver The address where the loan amount will be sent to.\n */\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver\n ) public override whenProtocolNotPaused returns (uint256 bidId_) {\n bidId_ = _submitBid(\n _lendingToken,\n _marketplaceId,\n _principal,\n _duration,\n _APR,\n _metadataURI,\n _receiver\n );\n }\n\n /**\n * @notice Function for a borrower to create a bid for a loan with Collateral.\n * @param _lendingToken The lending token asset requested to be borrowed.\n * @param _marketplaceId The unique id of the marketplace for the bid.\n * @param _principal The principal amount of the loan bid.\n * @param _duration The recurrent length of time before which a payment is due.\n * @param _APR The proposed interest rate for the loan bid.\n * @param _metadataURI The URI for additional borrower loan information as part of loan bid.\n * @param _receiver The address where the loan amount will be sent to.\n * @param _collateralInfo Additional information about the collateral asset.\n */\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver,\n Collateral[] calldata _collateralInfo\n ) public override whenProtocolNotPaused returns (uint256 bidId_) {\n bidId_ = _submitBid(\n _lendingToken,\n _marketplaceId,\n _principal,\n _duration,\n _APR,\n _metadataURI,\n _receiver\n );\n\n bool validation = collateralManager.commitCollateral(\n bidId_,\n _collateralInfo\n );\n\n require(\n validation == true,\n \"C bal NV\"\n );\n }\n\n function _submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver\n ) internal virtual returns (uint256 bidId_) {\n address sender = _msgSenderForMarket(_marketplaceId);\n\n (bool isVerified, ) = marketRegistry.isVerifiedBorrower(\n _marketplaceId,\n sender\n );\n\n require(isVerified, \"Borrower NV\");\n\n require(\n marketRegistry.isMarketOpen(_marketplaceId),\n \"Mkt C\"\n );\n\n // Set response bid ID.\n bidId_ = bidId;\n\n // Create and store our bid into the mapping\n Bid storage bid = bids[bidId];\n bid.borrower = sender;\n bid.receiver = _receiver != address(0) ? _receiver : bid.borrower;\n bid.marketplaceId = _marketplaceId;\n bid.loanDetails.lendingToken = IERC20(_lendingToken);\n bid.loanDetails.principal = _principal;\n bid.loanDetails.loanDuration = _duration;\n bid.loanDetails.timestamp = uint32(block.timestamp);\n\n // Set payment cycle type based on market setting (custom or monthly)\n (bid.terms.paymentCycle, bidPaymentCycleType[bidId]) = marketRegistry\n .getPaymentCycle(_marketplaceId);\n\n bid.terms.APR = _APR;\n\n bidDefaultDuration[bidId] = marketRegistry.getPaymentDefaultDuration(\n _marketplaceId\n );\n\n bidExpirationTime[bidId] = marketRegistry.getBidExpirationTime(\n _marketplaceId\n );\n\n bid.paymentType = marketRegistry.getPaymentType(_marketplaceId);\n\n bid.terms.paymentCycleAmount = V2Calculations\n .calculatePaymentCycleAmount(\n bid.paymentType,\n bidPaymentCycleType[bidId],\n _principal,\n _duration,\n bid.terms.paymentCycle,\n _APR\n );\n\n uris[bidId] = _metadataURI;\n bid.state = BidState.PENDING;\n\n emit SubmittedBid(\n bidId,\n bid.borrower,\n bid.receiver,\n keccak256(abi.encodePacked(_metadataURI))\n );\n\n // Store bid inside borrower bids mapping\n borrowerBids[bid.borrower].push(bidId);\n\n // Increment bid id counter\n bidId++;\n }\n\n /**\n * @notice Function for a borrower to cancel their pending bid.\n * @param _bidId The id of the bid to cancel.\n */\n function cancelBid(uint256 _bidId) external {\n if (\n _msgSenderForMarket(bids[_bidId].marketplaceId) !=\n bids[_bidId].borrower\n ) {\n revert ActionNotAllowed({\n bidId: _bidId,\n action: \"cancelBid\",\n message: \"Not bid owner\" //this is a TON of storage space\n });\n }\n _cancelBid(_bidId);\n }\n\n /**\n * @notice Function for a market owner to cancel a bid in the market.\n * @param _bidId The id of the bid to cancel.\n */\n function marketOwnerCancelBid(uint256 _bidId) external {\n if (\n _msgSender() !=\n marketRegistry.getMarketOwner(bids[_bidId].marketplaceId)\n ) {\n revert ActionNotAllowed({\n bidId: _bidId,\n action: \"marketOwnerCancelBid\",\n message: \"Not market owner\" //this is a TON of storage space \n });\n }\n _cancelBid(_bidId);\n emit MarketOwnerCancelledBid(_bidId);\n }\n\n /**\n * @notice Function for users to cancel a bid.\n * @param _bidId The id of the bid to be cancelled.\n */\n function _cancelBid(uint256 _bidId)\n internal\n virtual\n pendingBid(_bidId, \"cancelBid\")\n {\n // Set the bid state to CANCELLED\n bids[_bidId].state = BidState.CANCELLED;\n\n // Emit CancelledBid event\n emit CancelledBid(_bidId);\n }\n\n /**\n * @notice Function for a lender to accept a proposed loan bid.\n * @param _bidId The id of the loan bid to accept.\n */\n function lenderAcceptBid(uint256 _bidId)\n external\n override\n pendingBid(_bidId, \"lenderAcceptBid\")\n whenProtocolNotPaused\n returns (\n uint256 amountToProtocol,\n uint256 amountToMarketplace,\n uint256 amountToBorrower\n )\n {\n // Retrieve bid\n Bid storage bid = bids[_bidId];\n\n address sender = _msgSenderForMarket(bid.marketplaceId);\n\n (bool isVerified, ) = marketRegistry.isVerifiedLender(\n bid.marketplaceId,\n sender\n );\n require(isVerified, \"NV\");\n\n require(\n !marketRegistry.isMarketClosed(bid.marketplaceId),\n \"Market is closed\"\n );\n\n require(!isLoanExpired(_bidId), \"BE\");\n\n // Set timestamp\n bid.loanDetails.acceptedTimestamp = uint32(block.timestamp);\n bid.loanDetails.lastRepaidTimestamp = uint32(block.timestamp);\n\n // Mark borrower's request as accepted\n bid.state = BidState.ACCEPTED;\n\n // Declare the bid acceptor as the lender of the bid\n bid.lender = sender;\n\n // Tell the collateral manager to deploy the escrow and pull funds from the borrower if applicable\n collateralManager.deployAndDeposit(_bidId);\n\n // Transfer funds to borrower from the lender\n amountToProtocol = bid.loanDetails.principal.percent(protocolFee());\n amountToMarketplace = bid.loanDetails.principal.percent(\n marketRegistry.getMarketplaceFee(bid.marketplaceId)\n );\n amountToBorrower =\n bid.loanDetails.principal -\n amountToProtocol -\n amountToMarketplace;\n\n //transfer fee to protocol\n if (amountToProtocol > 0) {\n bid.loanDetails.lendingToken.safeTransferFrom(\n sender,\n owner(),\n amountToProtocol\n );\n }\n\n //transfer fee to marketplace\n if (amountToMarketplace > 0) {\n bid.loanDetails.lendingToken.safeTransferFrom(\n sender,\n marketRegistry.getMarketFeeRecipient(bid.marketplaceId),\n amountToMarketplace\n );\n }\n\n //transfer funds to borrower\n if (amountToBorrower > 0) {\n bid.loanDetails.lendingToken.safeTransferFrom(\n sender,\n bid.receiver,\n amountToBorrower\n );\n }\n\n // Record volume filled by lenders\n lenderVolumeFilled[address(bid.loanDetails.lendingToken)][sender] += bid\n .loanDetails\n .principal;\n totalVolumeFilled[address(bid.loanDetails.lendingToken)] += bid\n .loanDetails\n .principal;\n\n // Add borrower's active bid\n _borrowerBidsActive[bid.borrower].add(_bidId);\n\n // Emit AcceptedBid\n emit AcceptedBid(_bidId, sender);\n\n emit FeePaid(_bidId, \"protocol\", amountToProtocol);\n emit FeePaid(_bidId, \"marketplace\", amountToMarketplace);\n }\n\n function claimLoanNFT(uint256 _bidId)\n external\n acceptedLoan(_bidId, \"claimLoanNFT\")\n whenProtocolNotPaused\n {\n // Retrieve bid\n Bid storage bid = bids[_bidId];\n\n address sender = _msgSenderForMarket(bid.marketplaceId);\n require(sender == bid.lender, \"NV Lender\");\n\n // set lender address to the lender manager so we know to check the owner of the NFT for the true lender\n bid.lender = address(USING_LENDER_MANAGER);\n\n // mint an NFT with the lender manager\n lenderManager.registerLoan(_bidId, sender);\n }\n\n /**\n * @notice Function for users to make the minimum amount due for an active loan.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanMinimum(uint256 _bidId)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n (\n uint256 owedPrincipal,\n uint256 duePrincipal,\n uint256 interest\n ) = V2Calculations.calculateAmountOwed(\n bids[_bidId],\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n _repayLoan(\n _bidId,\n Payment({ principal: duePrincipal, interest: interest }),\n owedPrincipal + interest,\n true\n );\n }\n\n /**\n * @notice Function for users to repay an active loan in full.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanFull(uint256 _bidId)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n _repayLoanFull(_bidId, true);\n }\n\n // function that the borrower (ideally) sends to repay the loan\n /**\n * @notice Function for users to make a payment towards an active loan.\n * @param _bidId The id of the loan to make the payment towards.\n * @param _amount The amount of the payment.\n */\n function repayLoan(uint256 _bidId, uint256 _amount)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n _repayLoanAtleastMinimum(_bidId, _amount, true);\n }\n\n /**\n * @notice Function for users to repay an active loan in full.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanFullWithoutCollateralWithdraw(uint256 _bidId)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n _repayLoanFull(_bidId, false);\n }\n\n function repayLoanWithoutCollateralWithdraw(uint256 _bidId, uint256 _amount)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n _repayLoanAtleastMinimum(_bidId, _amount, false);\n }\n\n function _repayLoanFull(uint256 _bidId, bool withdrawCollateral) internal {\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bids[_bidId],\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n _repayLoan(\n _bidId,\n Payment({ principal: owedPrincipal, interest: interest }),\n owedPrincipal + interest,\n withdrawCollateral\n );\n }\n\n function _repayLoanAtleastMinimum(\n uint256 _bidId,\n uint256 _amount,\n bool withdrawCollateral\n ) internal {\n (\n uint256 owedPrincipal,\n uint256 duePrincipal,\n uint256 interest\n ) = V2Calculations.calculateAmountOwed(\n bids[_bidId],\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n uint256 minimumOwed = duePrincipal + interest;\n\n // If amount is less than minimumOwed, we revert\n if (_amount < minimumOwed) {\n revert PaymentNotMinimum(_bidId, _amount, minimumOwed);\n }\n\n _repayLoan(\n _bidId,\n Payment({ principal: _amount - interest, interest: interest }),\n owedPrincipal + interest,\n withdrawCollateral\n );\n }\n\n \n\n\n function lenderCloseLoan(uint256 _bidId)\n external whenProtocolNotPaused whenLiquidationsNotPaused\n acceptedLoan(_bidId, \"lenderClaimCollateral\")\n {\n Bid storage bid = bids[_bidId];\n address _collateralRecipient = getLoanLender(_bidId);\n\n _lenderCloseLoanWithRecipient(_bidId, _collateralRecipient);\n }\n\n /**\n * @notice Function for lender to claim collateral for a defaulted loan. The only purpose of a CLOSED loan is to make collateral claimable by lender.\n * @param _bidId The id of the loan to set to CLOSED status.\n */\n function lenderCloseLoanWithRecipient(\n uint256 _bidId,\n address _collateralRecipient\n ) external whenProtocolNotPaused whenLiquidationsNotPaused {\n _lenderCloseLoanWithRecipient(_bidId, _collateralRecipient);\n }\n\n function _lenderCloseLoanWithRecipient(\n uint256 _bidId,\n address _collateralRecipient\n ) internal acceptedLoan(_bidId, \"lenderClaimCollateral\") {\n require(isLoanDefaulted(_bidId), \"ND\");\n\n Bid storage bid = bids[_bidId];\n bid.state = BidState.CLOSED;\n\n address sender = _msgSenderForMarket(bid.marketplaceId);\n require(sender == getLoanLender(_bidId), \"NLL\");\n\n \n collateralManager.lenderClaimCollateralWithRecipient(_bidId, _collateralRecipient);\n\n emit LoanClosed(_bidId);\n }\n\n /**\n * @notice Function for users to liquidate a defaulted loan.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function liquidateLoanFull(uint256 _bidId)\n external whenProtocolNotPaused whenLiquidationsNotPaused\n acceptedLoan(_bidId, \"liquidateLoan\")\n {\n Bid storage bid = bids[_bidId];\n\n // If loan is backed by collateral, withdraw and send to the liquidator\n address recipient = _msgSenderForMarket(bid.marketplaceId);\n\n _liquidateLoanFull(_bidId, recipient);\n }\n\n function liquidateLoanFullWithRecipient(uint256 _bidId, address _recipient)\n external whenProtocolNotPaused whenLiquidationsNotPaused\n acceptedLoan(_bidId, \"liquidateLoan\")\n {\n _liquidateLoanFull(_bidId, _recipient);\n }\n\n /**\n * @notice Function for users to liquidate a defaulted loan.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function _liquidateLoanFull(uint256 _bidId, address _recipient)\n internal\n acceptedLoan(_bidId, \"liquidateLoan\")\n {\n require(isLoanLiquidateable(_bidId), \"NL\");\n\n Bid storage bid = bids[_bidId];\n\n // change state here to prevent re-entrancy\n bid.state = BidState.LIQUIDATED;\n\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bid,\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n\n //this sets the state to 'repaid'\n _repayLoan(\n _bidId,\n Payment({ principal: owedPrincipal, interest: interest }),\n owedPrincipal + interest,\n false\n );\n\n collateralManager.liquidateCollateral(_bidId, _recipient);\n\n address liquidator = _msgSenderForMarket(bid.marketplaceId);\n\n emit LoanLiquidated(_bidId, liquidator);\n }\n\n /**\n * @notice Internal function to make a loan payment.\n * @dev Updates the bid's `status` to `PAID` only if it is not already marked as `LIQUIDATED`\n * @param _bidId The id of the loan to make the payment towards.\n * @param _payment The Payment struct with payments amounts towards principal and interest respectively.\n * @param _owedAmount The total amount owed on the loan.\n */\n function _repayLoan(\n uint256 _bidId,\n Payment memory _payment,\n uint256 _owedAmount,\n bool _shouldWithdrawCollateral\n ) internal virtual {\n Bid storage bid = bids[_bidId];\n uint256 paymentAmount = _payment.principal + _payment.interest;\n\n RepMark mark = reputationManager.updateAccountReputation(\n bid.borrower,\n _bidId\n );\n\n // Check if we are sending a payment or amount remaining\n if (paymentAmount >= _owedAmount) {\n paymentAmount = _owedAmount;\n\n if (bid.state != BidState.LIQUIDATED) {\n bid.state = BidState.PAID;\n }\n\n // Remove borrower's active bid\n _borrowerBidsActive[bid.borrower].remove(_bidId);\n\n // If loan is is being liquidated and backed by collateral, withdraw and send to borrower\n if (_shouldWithdrawCollateral) { \n \n // _getCollateralManagerForBid(_bidId).withdraw(_bidId);\n collateralManager.withdraw(_bidId);\n }\n\n emit LoanRepaid(_bidId);\n } else {\n emit LoanRepayment(_bidId);\n }\n\n _sendOrEscrowFunds(_bidId, _payment); //send or escrow the funds\n\n // update our mappings\n bid.loanDetails.totalRepaid.principal += _payment.principal;\n bid.loanDetails.totalRepaid.interest += _payment.interest;\n bid.loanDetails.lastRepaidTimestamp = uint32(block.timestamp);\n\n // If the loan is paid in full and has a mark, we should update the current reputation\n if (mark != RepMark.Good) {\n reputationManager.updateAccountReputation(bid.borrower, _bidId);\n }\n }\n\n\n function _sendOrEscrowFunds(uint256 _bidId, Payment memory _payment)\n internal\n {\n Bid storage bid = bids[_bidId];\n address lender = getLoanLender(_bidId);\n\n uint256 _paymentAmount = _payment.principal + _payment.interest;\n\n try \n\n bid.loanDetails.lendingToken.transferFrom{ gas: 100000 }(\n _msgSenderForMarket(bid.marketplaceId),\n lender,\n _paymentAmount\n )\n {} catch {\n address sender = _msgSenderForMarket(bid.marketplaceId);\n\n uint256 balanceBefore = bid.loanDetails.lendingToken.balanceOf(\n address(this)\n ); \n\n //if unable, pay to escrow\n bid.loanDetails.lendingToken.safeTransferFrom(\n sender,\n address(this),\n _paymentAmount\n );\n\n uint256 balanceAfter = bid.loanDetails.lendingToken.balanceOf(\n address(this)\n );\n\n //used for fee-on-send tokens\n uint256 paymentAmountReceived = balanceAfter - balanceBefore;\n\n bid.loanDetails.lendingToken.approve(\n address(escrowVault),\n paymentAmountReceived\n );\n\n IEscrowVault(escrowVault).deposit(\n lender,\n address(bid.loanDetails.lendingToken),\n paymentAmountReceived\n );\n }\n\n address loanRepaymentListener = repaymentListenerForBid[_bidId];\n\n if (loanRepaymentListener != address(0)) {\n require(gasleft() >= 80000, \"NR gas\"); //fixes the 63/64 remaining issue\n try\n ILoanRepaymentListener(loanRepaymentListener).repayLoanCallback{\n gas: 80000\n }( //limit gas costs to prevent lender preventing repayments\n _bidId,\n _msgSenderForMarket(bid.marketplaceId),\n _payment.principal,\n _payment.interest\n )\n {} catch {}\n }\n }\n\n\n\n\n /**\n * @notice Calculates the total amount owed for a loan bid at a specific timestamp.\n * @param _bidId The id of the loan bid to calculate the owed amount for.\n * @param _timestamp The timestamp at which to calculate the loan owed amount at.\n */\n function calculateAmountOwed(uint256 _bidId, uint256 _timestamp)\n public\n view\n returns (Payment memory owed)\n {\n Bid storage bid = bids[_bidId];\n if (\n bid.state != BidState.ACCEPTED ||\n bid.loanDetails.acceptedTimestamp >= _timestamp\n ) return owed;\n\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bid,\n _timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n\n owed.principal = owedPrincipal;\n owed.interest = interest;\n }\n\n /**\n * @notice Calculates the minimum payment amount due for a loan at a specific timestamp.\n * @param _bidId The id of the loan bid to get the payment amount for.\n * @param _timestamp The timestamp at which to get the due payment at.\n */\n function calculateAmountDue(uint256 _bidId, uint256 _timestamp)\n public\n view\n returns (Payment memory due)\n {\n Bid storage bid = bids[_bidId];\n if (\n bids[_bidId].state != BidState.ACCEPTED ||\n bid.loanDetails.acceptedTimestamp >= _timestamp\n ) return due;\n\n (, uint256 duePrincipal, uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bid,\n _timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n due.principal = duePrincipal;\n due.interest = interest;\n }\n\n /**\n * @notice Returns the next due date for a loan payment.\n * @param _bidId The id of the loan bid.\n */\n function calculateNextDueDate(uint256 _bidId)\n public\n view\n returns (uint32 dueDate_)\n {\n Bid storage bid = bids[_bidId];\n if (bids[_bidId].state != BidState.ACCEPTED) return dueDate_;\n\n return\n V2Calculations.calculateNextDueDate(\n bid.loanDetails.acceptedTimestamp,\n bid.terms.paymentCycle,\n bid.loanDetails.loanDuration,\n lastRepaidTimestamp(_bidId),\n bidPaymentCycleType[_bidId]\n );\n }\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n */\n function isPaymentLate(uint256 _bidId) public view override returns (bool) {\n if (bids[_bidId].state != BidState.ACCEPTED) return false;\n return uint32(block.timestamp) > calculateNextDueDate(_bidId);\n }\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n * @return bool True if the loan is defaulted.\n */\n function isLoanDefaulted(uint256 _bidId)\n public\n view\n override\n returns (bool)\n {\n return _isLoanDefaulted(_bidId, 0);\n }\n\n /**\n * @notice Checks to see if a loan was delinquent for longer than liquidation delay.\n * @param _bidId The id of the loan bid to check for.\n * @return bool True if the loan is liquidateable.\n */\n function isLoanLiquidateable(uint256 _bidId)\n public\n view\n override\n returns (bool)\n {\n return _isLoanDefaulted(_bidId, LIQUIDATION_DELAY);\n }\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n * @param _additionalDelay Amount of additional seconds after a loan defaulted to allow a liquidation.\n * @return bool True if the loan is liquidateable.\n */\n function _isLoanDefaulted(uint256 _bidId, uint32 _additionalDelay)\n internal\n view\n returns (bool)\n {\n Bid storage bid = bids[_bidId];\n\n // Make sure loan cannot be liquidated if it is not active\n if (bid.state != BidState.ACCEPTED) return false;\n\n uint32 defaultDuration = bidDefaultDuration[_bidId];\n\n uint32 dueDate = calculateNextDueDate(_bidId);\n\n return\n uint32(block.timestamp) >\n dueDate + defaultDuration + _additionalDelay;\n }\n\n function getEscrowVault() external view returns(address){\n return address(escrowVault);\n }\n\n function getBidState(uint256 _bidId)\n external\n view\n override\n returns (BidState)\n {\n return bids[_bidId].state;\n }\n\n function getBorrowerActiveLoanIds(address _borrower)\n external\n view\n override\n returns (uint256[] memory)\n {\n return _borrowerBidsActive[_borrower].values();\n }\n\n function getBorrowerLoanIds(address _borrower)\n external\n view\n returns (uint256[] memory)\n {\n return borrowerBids[_borrower];\n }\n\n /**\n * @notice Checks to see if a pending loan has expired so it is no longer able to be accepted.\n * @param _bidId The id of the loan bid to check for.\n */\n function isLoanExpired(uint256 _bidId) public view returns (bool) {\n Bid storage bid = bids[_bidId];\n\n if (bid.state != BidState.PENDING) return false;\n if (bidExpirationTime[_bidId] == 0) return false;\n\n return (uint32(block.timestamp) >\n bid.loanDetails.timestamp + bidExpirationTime[_bidId]);\n }\n\n /**\n * @notice Returns the last repaid timestamp for a loan.\n * @param _bidId The id of the loan bid to get the timestamp for.\n */\n function lastRepaidTimestamp(uint256 _bidId) public view returns (uint32) {\n return V2Calculations.lastRepaidTimestamp(bids[_bidId]);\n }\n\n /**\n * @notice Returns the borrower address for a given bid.\n * @param _bidId The id of the bid/loan to get the borrower for.\n * @return borrower_ The address of the borrower associated with the bid.\n */\n function getLoanBorrower(uint256 _bidId)\n public\n view\n returns (address borrower_)\n {\n borrower_ = bids[_bidId].borrower;\n }\n\n /**\n * @notice Returns the lender address for a given bid. If the stored lender address is the `LenderManager` NFT address, return the `ownerOf` for the bid ID.\n * @param _bidId The id of the bid/loan to get the lender for.\n * @return lender_ The address of the lender associated with the bid.\n */\n function getLoanLender(uint256 _bidId)\n public\n view\n returns (address lender_)\n {\n lender_ = bids[_bidId].lender;\n\n if (lender_ == address(USING_LENDER_MANAGER)) {\n return lenderManager.ownerOf(_bidId);\n }\n\n //this is left in for backwards compatibility only\n if (lender_ == address(lenderManager)) {\n return lenderManager.ownerOf(_bidId);\n }\n }\n\n function getLoanLendingToken(uint256 _bidId)\n external\n view\n returns (address token_)\n {\n token_ = address(bids[_bidId].loanDetails.lendingToken);\n }\n\n function getLoanMarketId(uint256 _bidId)\n external\n view\n returns (uint256 _marketId)\n {\n _marketId = bids[_bidId].marketplaceId;\n }\n\n function getLoanSummary(uint256 _bidId)\n external\n view\n returns (\n address borrower,\n address lender,\n uint256 marketId,\n address principalTokenAddress,\n uint256 principalAmount,\n uint32 acceptedTimestamp,\n uint32 lastRepaidTimestamp,\n BidState bidState\n )\n {\n Bid storage bid = bids[_bidId];\n\n borrower = bid.borrower;\n lender = getLoanLender(_bidId);\n marketId = bid.marketplaceId;\n principalTokenAddress = address(bid.loanDetails.lendingToken);\n principalAmount = bid.loanDetails.principal;\n acceptedTimestamp = bid.loanDetails.acceptedTimestamp;\n lastRepaidTimestamp = V2Calculations.lastRepaidTimestamp(bids[_bidId]);\n bidState = bid.state;\n }\n\n // Additions for lender groups\n\n function getLoanDefaultTimestamp(uint256 _bidId)\n public\n view\n returns (uint256)\n {\n Bid storage bid = bids[_bidId];\n\n uint32 defaultDuration = _getBidDefaultDuration(_bidId);\n\n uint32 dueDate = calculateNextDueDate(_bidId);\n\n return dueDate + defaultDuration;\n }\n \n function setRepaymentListenerForBid(uint256 _bidId, address _listener) external {\n uint256 codeSize;\n assembly {\n codeSize := extcodesize(_listener) \n }\n require(codeSize > 0, \"Not a contract\");\n address sender = _msgSenderForMarket(bids[_bidId].marketplaceId);\n\n require(\n sender == getLoanLender(_bidId),\n \"Not lender\"\n );\n\n repaymentListenerForBid[_bidId] = _listener;\n }\n\n\n\n\n function getRepaymentListenerForBid(uint256 _bidId)\n external\n view\n returns (address)\n {\n return repaymentListenerForBid[_bidId];\n }\n\n // ----------\n\n function _getBidPaymentCycleType(uint256 _bidId)\n internal\n view\n returns (PaymentCycleType)\n {\n \n\n return bidPaymentCycleType[_bidId];\n }\n\n function _getBidPaymentCycleDuration(uint256 _bidId)\n internal\n view\n returns (uint32)\n {\n \n\n Bid storage bid = bids[_bidId];\n\n return bid.terms.paymentCycle;\n }\n\n function _getBidDefaultDuration(uint256 _bidId)\n internal\n view\n returns (uint32)\n {\n \n\n return bidDefaultDuration[_bidId];\n }\n\n // -----\n\n /** OpenZeppelin Override Functions **/\n\n function _msgSender()\n internal\n view\n virtual\n override(ERC2771ContextUpgradeable, ContextUpgradeable)\n returns (address sender)\n {\n sender = ERC2771ContextUpgradeable._msgSender();\n }\n\n function _msgData()\n internal\n view\n virtual\n override(ERC2771ContextUpgradeable, ContextUpgradeable)\n returns (bytes calldata)\n {\n return ERC2771ContextUpgradeable._msgData();\n }\n}\n" + }, + "contracts/TellerV2Autopay.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./interfaces/ITellerV2.sol\";\nimport \"./interfaces/ITellerV2Autopay.sol\";\n\nimport \"./libraries/NumbersLib.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Payment } from \"./TellerV2Storage.sol\";\n\n/**\n * @dev Helper contract to autopay loans\n */\ncontract TellerV2Autopay is OwnableUpgradeable, ITellerV2Autopay {\n using SafeERC20 for ERC20;\n using NumbersLib for uint256;\n\n ITellerV2 public immutable tellerV2;\n\n //bidId => enabled\n mapping(uint256 => bool) public loanAutoPayEnabled;\n\n // Autopay fee set for automatic loan payments\n uint16 private _autopayFee;\n\n /**\n * @notice This event is emitted when a loan is autopaid.\n * @param bidId The id of the bid/loan which was repaid.\n * @param msgsender The account that called the method\n */\n event AutoPaidLoanMinimum(uint256 indexed bidId, address indexed msgsender);\n\n /**\n * @notice This event is emitted when loan autopayments are enabled or disabled.\n * @param bidId The id of the bid/loan.\n * @param enabled Whether the autopayments are enabled or disabled\n */\n event AutoPayEnabled(uint256 indexed bidId, bool enabled);\n\n /**\n * @notice This event is emitted when the autopay fee has been updated.\n * @param newFee The new autopay fee set.\n * @param oldFee The previously set autopay fee.\n */\n event AutopayFeeSet(uint16 newFee, uint16 oldFee);\n\n constructor(address _protocolAddress) {\n tellerV2 = ITellerV2(_protocolAddress);\n }\n\n /**\n * @notice Initialized the proxy.\n * @param _fee The fee collected for automatic payment processing.\n * @param _owner The address of the ownership to be transferred to.\n */\n function initialize(uint16 _fee, address _owner) external initializer {\n _transferOwnership(_owner);\n _setAutopayFee(_fee);\n }\n\n /**\n * @notice Let the owner of the contract set a new autopay fee.\n * @param _newFee The new autopay fee to set.\n */\n function setAutopayFee(uint16 _newFee) public virtual onlyOwner {\n _setAutopayFee(_newFee);\n }\n\n function _setAutopayFee(uint16 _newFee) internal {\n // Skip if the fee is the same\n if (_newFee == _autopayFee) return;\n uint16 oldFee = _autopayFee;\n _autopayFee = _newFee;\n emit AutopayFeeSet(_newFee, oldFee);\n }\n\n /**\n * @notice Returns the current autopay fee.\n */\n function getAutopayFee() public view virtual returns (uint16) {\n return _autopayFee;\n }\n\n /**\n * @notice Function for a borrower to enable or disable autopayments\n * @param _bidId The id of the bid to cancel.\n * @param _autoPayEnabled boolean for allowing autopay on a loan\n */\n function setAutoPayEnabled(uint256 _bidId, bool _autoPayEnabled) external {\n require(\n _msgSender() == tellerV2.getLoanBorrower(_bidId),\n \"Only the borrower can set autopay\"\n );\n\n loanAutoPayEnabled[_bidId] = _autoPayEnabled;\n\n emit AutoPayEnabled(_bidId, _autoPayEnabled);\n }\n\n /**\n * @notice Function for a minimum autopayment to be performed on a loan\n * @param _bidId The id of the bid to repay.\n */\n function autoPayLoanMinimum(uint256 _bidId) external {\n require(\n loanAutoPayEnabled[_bidId],\n \"Autopay is not enabled for that loan\"\n );\n\n address lendingToken = ITellerV2(tellerV2).getLoanLendingToken(_bidId);\n address borrower = ITellerV2(tellerV2).getLoanBorrower(_bidId);\n\n uint256 amountToRepayMinimum = getEstimatedMinimumPayment(\n _bidId,\n block.timestamp\n );\n uint256 autopayFeeAmount = amountToRepayMinimum.percent(\n getAutopayFee()\n );\n\n // Pull lendingToken in from the borrower to this smart contract\n ERC20(lendingToken).safeTransferFrom(\n borrower,\n address(this),\n amountToRepayMinimum + autopayFeeAmount\n );\n\n // Transfer fee to msg sender\n ERC20(lendingToken).safeTransfer(_msgSender(), autopayFeeAmount);\n\n // Approve the lendingToken to tellerV2\n ERC20(lendingToken).approve(address(tellerV2), amountToRepayMinimum);\n\n // Use that lendingToken to repay the loan\n tellerV2.repayLoan(_bidId, amountToRepayMinimum);\n\n emit AutoPaidLoanMinimum(_bidId, msg.sender);\n }\n\n function getEstimatedMinimumPayment(uint256 _bidId, uint256 _timestamp)\n public\n virtual\n returns (uint256 _amount)\n {\n Payment memory estimatedPayment = tellerV2.calculateAmountDue(\n _bidId,\n _timestamp\n );\n\n _amount = estimatedPayment.principal + estimatedPayment.interest;\n }\n}\n" + }, + "contracts/TellerV2Context.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./TellerV2Storage.sol\";\nimport \"./ERC2771ContextUpgradeable.sol\";\n\n/**\n * @dev This contract should not use any storage\n */\n\nabstract contract TellerV2Context is\n ERC2771ContextUpgradeable,\n TellerV2Storage\n{\n using EnumerableSet for EnumerableSet.AddressSet;\n\n event TrustedMarketForwarderSet(\n uint256 indexed marketId,\n address forwarder,\n address sender\n );\n event MarketForwarderApproved(\n uint256 indexed marketId,\n address indexed forwarder,\n address sender\n );\n event MarketForwarderRenounced(\n uint256 indexed marketId,\n address indexed forwarder,\n address sender\n );\n\n constructor(address trustedForwarder)\n ERC2771ContextUpgradeable(trustedForwarder)\n {}\n\n /**\n * @notice Checks if an address is a trusted forwarder contract for a given market.\n * @param _marketId An ID for a lending market.\n * @param _trustedMarketForwarder An address to check if is a trusted forwarder in the given market.\n * @return A boolean indicating the forwarder address is trusted in a market.\n */\n function isTrustedMarketForwarder(\n uint256 _marketId,\n address _trustedMarketForwarder\n ) public view returns (bool) {\n return\n _trustedMarketForwarders[_marketId] == _trustedMarketForwarder ||\n lenderCommitmentForwarder == _trustedMarketForwarder;\n }\n\n /**\n * @notice Checks if an account has approved a forwarder for a market.\n * @param _marketId An ID for a lending market.\n * @param _forwarder A forwarder contract address.\n * @param _account The address to verify set an approval.\n * @return A boolean indicating if an approval was set.\n */\n function hasApprovedMarketForwarder(\n uint256 _marketId,\n address _forwarder,\n address _account\n ) public view returns (bool) {\n return\n isTrustedMarketForwarder(_marketId, _forwarder) &&\n _approvedForwarderSenders[_forwarder].contains(_account);\n }\n\n /**\n * @notice Sets a trusted forwarder for a lending market.\n * @notice The caller must owner the market given. See {MarketRegistry}\n * @param _marketId An ID for a lending market.\n * @param _forwarder A forwarder contract address.\n */\n function setTrustedMarketForwarder(uint256 _marketId, address _forwarder)\n external\n {\n require(\n marketRegistry.getMarketOwner(_marketId) == _msgSender(),\n \"Caller must be the market owner\"\n );\n _trustedMarketForwarders[_marketId] = _forwarder;\n emit TrustedMarketForwarderSet(_marketId, _forwarder, _msgSender());\n }\n\n /**\n * @notice Approves a forwarder contract to use their address as a sender for a specific market.\n * @notice The forwarder given must be trusted by the market given.\n * @param _marketId An ID for a lending market.\n * @param _forwarder A forwarder contract address.\n */\n function approveMarketForwarder(uint256 _marketId, address _forwarder)\n external\n {\n require(\n isTrustedMarketForwarder(_marketId, _forwarder),\n \"Forwarder must be trusted by the market\"\n );\n _approvedForwarderSenders[_forwarder].add(_msgSender());\n emit MarketForwarderApproved(_marketId, _forwarder, _msgSender());\n }\n\n /**\n * @notice Renounces approval of a market forwarder\n * @param _marketId An ID for a lending market.\n * @param _forwarder A forwarder contract address.\n */\n function renounceMarketForwarder(uint256 _marketId, address _forwarder)\n external\n {\n if (_approvedForwarderSenders[_forwarder].contains(_msgSender())) {\n _approvedForwarderSenders[_forwarder].remove(_msgSender());\n emit MarketForwarderRenounced(_marketId, _forwarder, _msgSender());\n }\n }\n\n /**\n * @notice Retrieves the function caller address by checking the appended calldata if the _actual_ caller is a trusted forwarder.\n * @param _marketId An ID for a lending market.\n * @return sender The address to use as the function caller.\n */\n function _msgSenderForMarket(uint256 _marketId)\n internal\n view\n virtual\n returns (address)\n {\n if (\n msg.data.length >= 20 &&\n isTrustedMarketForwarder(_marketId, _msgSender())\n ) {\n address sender;\n assembly {\n sender := shr(96, calldataload(sub(calldatasize(), 20)))\n }\n // Ensure the appended sender address approved the forwarder\n require(\n _approvedForwarderSenders[_msgSender()].contains(sender),\n \"Sender must approve market forwarder\"\n );\n return sender;\n }\n\n return _msgSender();\n }\n\n /**\n * @notice Retrieves the actual function calldata from a trusted forwarder call.\n * @param _marketId An ID for a lending market to verify if the caller is a trusted forwarder.\n * @return calldata The modified bytes array of the function calldata without the appended sender's address.\n */\n function _msgDataForMarket(uint256 _marketId)\n internal\n view\n virtual\n returns (bytes calldata)\n {\n if (isTrustedMarketForwarder(_marketId, _msgSender())) {\n return msg.data[:msg.data.length - 20];\n } else {\n return _msgData();\n }\n }\n}\n" + }, + "contracts/TellerV2MarketForwarder_G1.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./interfaces/ITellerV2.sol\";\n\nimport \"./interfaces/IMarketRegistry.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\n\n/**\n * @dev Simple helper contract to forward an encoded function call to the TellerV2 contract. See {TellerV2Context}\n */\nabstract contract TellerV2MarketForwarder_G1 is\n Initializable,\n ContextUpgradeable\n{\n using AddressUpgradeable for address;\n\n address public immutable _tellerV2;\n address public immutable _marketRegistry;\n\n struct CreateLoanArgs {\n uint256 marketId;\n address lendingToken;\n uint256 principal;\n uint32 duration;\n uint16 interestRate;\n string metadataURI;\n address recipient;\n }\n\n constructor(address _protocolAddress, address _marketRegistryAddress) {\n _tellerV2 = _protocolAddress;\n _marketRegistry = _marketRegistryAddress;\n }\n\n function getTellerV2() public view returns (address) {\n return _tellerV2;\n }\n\n function getMarketRegistry() public view returns (address) {\n return _marketRegistry;\n }\n\n function getTellerV2MarketOwner(uint256 marketId) public returns (address) {\n return IMarketRegistry(getMarketRegistry()).getMarketOwner(marketId);\n }\n\n /**\n * @dev Performs function call to the TellerV2 contract by appending an address to the calldata.\n * @param _data The encoded function calldata on TellerV2.\n * @param _msgSender The address that should be treated as the underlying function caller.\n * @return The encoded response from the called function.\n *\n * Requirements:\n * - The {_msgSender} address must set an approval on TellerV2 for this forwarder contract __before__ making this call.\n */\n function _forwardCall(bytes memory _data, address _msgSender)\n internal\n returns (bytes memory)\n {\n return\n address(_tellerV2).functionCall(\n abi.encodePacked(_data, _msgSender)\n );\n }\n\n /**\n * @notice Creates a new loan using the TellerV2 lending protocol.\n * @param _createLoanArgs Details describing the loan agreement.]\n * @param _borrower The borrower address for the new loan.\n */\n function _submitBid(\n CreateLoanArgs memory _createLoanArgs,\n address _borrower\n ) internal virtual returns (uint256 bidId) {\n bytes memory responseData;\n\n responseData = _forwardCall(\n abi.encodeWithSignature(\n \"submitBid(address,uint256,uint256,uint32,uint16,string,address)\",\n _createLoanArgs.lendingToken,\n _createLoanArgs.marketId,\n _createLoanArgs.principal,\n _createLoanArgs.duration,\n _createLoanArgs.interestRate,\n _createLoanArgs.metadataURI,\n _createLoanArgs.recipient\n ),\n _borrower\n );\n\n return abi.decode(responseData, (uint256));\n }\n\n /**\n * @notice Creates a new loan using the TellerV2 lending protocol.\n * @param _createLoanArgs Details describing the loan agreement.]\n * @param _borrower The borrower address for the new loan.\n */\n function _submitBidWithCollateral(\n CreateLoanArgs memory _createLoanArgs,\n Collateral[] memory _collateralInfo,\n address _borrower\n ) internal virtual returns (uint256 bidId) {\n bytes memory responseData;\n\n responseData = _forwardCall(\n abi.encodeWithSignature(\n \"submitBid(address,uint256,uint256,uint32,uint16,string,address,(uint8,uint256,uint256,address)[])\",\n _createLoanArgs.lendingToken,\n _createLoanArgs.marketId,\n _createLoanArgs.principal,\n _createLoanArgs.duration,\n _createLoanArgs.interestRate,\n _createLoanArgs.metadataURI,\n _createLoanArgs.recipient,\n _collateralInfo\n ),\n _borrower\n );\n\n return abi.decode(responseData, (uint256));\n }\n\n /**\n * @notice Accepts a new loan using the TellerV2 lending protocol.\n * @param _bidId The id of the new loan.\n * @param _lender The address of the lender who will provide funds for the new loan.\n */\n function _acceptBid(uint256 _bidId, address _lender)\n internal\n virtual\n returns (bool)\n {\n // Approve the borrower's loan\n _forwardCall(\n abi.encodeWithSelector(ITellerV2.lenderAcceptBid.selector, _bidId),\n _lender\n );\n\n return true;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/TellerV2MarketForwarder_G2.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./interfaces/ITellerV2.sol\";\n\nimport \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/ITellerV2MarketForwarder.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\n\n/**\n * @dev Simple helper contract to forward an encoded function call to the TellerV2 contract. See {TellerV2Context}\n */\nabstract contract TellerV2MarketForwarder_G2 is\n Initializable,\n ContextUpgradeable,\n ITellerV2MarketForwarder\n{\n using AddressUpgradeable for address;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable _tellerV2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable _marketRegistry;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _protocolAddress, address _marketRegistryAddress) {\n _tellerV2 = _protocolAddress;\n _marketRegistry = _marketRegistryAddress;\n }\n\n function getTellerV2() public view returns (address) {\n return _tellerV2;\n }\n\n function getMarketRegistry() public view returns (address) {\n return _marketRegistry;\n }\n\n function getTellerV2MarketOwner(uint256 marketId) public returns (address) {\n return IMarketRegistry(getMarketRegistry()).getMarketOwner(marketId);\n }\n\n /**\n * @dev Performs function call to the TellerV2 contract by appending an address to the calldata.\n * @param _data The encoded function calldata on TellerV2.\n * @param _msgSender The address that should be treated as the underlying function caller.\n * @return The encoded response from the called function.\n *\n * Requirements:\n * - The {_msgSender} address must set an approval on TellerV2 for this forwarder contract __before__ making this call.\n */\n function _forwardCall(bytes memory _data, address _msgSender)\n internal\n returns (bytes memory)\n {\n return\n address(_tellerV2).functionCall(\n abi.encodePacked(_data, _msgSender)\n );\n }\n\n /**\n * @notice Creates a new loan using the TellerV2 lending protocol.\n * @param _createLoanArgs Details describing the loan agreement.]\n * @param _borrower The borrower address for the new loan.\n */\n /*function _submitBid(\n CreateLoanArgs memory _createLoanArgs,\n address _borrower\n ) internal virtual returns (uint256 bidId) {\n bytes memory responseData;\n\n responseData = _forwardCall(\n abi.encodeWithSignature(\n \"submitBid(address,uint256,uint256,uint32,uint16,string,address)\",\n _createLoanArgs.lendingToken,\n _createLoanArgs.marketId,\n _createLoanArgs.principal,\n _createLoanArgs.duration,\n _createLoanArgs.interestRate,\n _createLoanArgs.metadataURI,\n _createLoanArgs.recipient\n ),\n _borrower\n );\n\n return abi.decode(responseData, (uint256));\n }*/\n\n /**\n * @notice Creates a new loan using the TellerV2 lending protocol.\n * @param _createLoanArgs Details describing the loan agreement.]\n * @param _borrower The borrower address for the new loan.\n */\n function _submitBidWithCollateral(\n CreateLoanArgs memory _createLoanArgs,\n address _borrower\n ) internal virtual returns (uint256 bidId) {\n bytes memory responseData;\n\n responseData = _forwardCall(\n abi.encodeWithSignature(\n \"submitBid(address,uint256,uint256,uint32,uint16,string,address,(uint8,uint256,uint256,address)[])\",\n _createLoanArgs.lendingToken,\n _createLoanArgs.marketId,\n _createLoanArgs.principal,\n _createLoanArgs.duration,\n _createLoanArgs.interestRate,\n _createLoanArgs.metadataURI,\n _createLoanArgs.recipient,\n _createLoanArgs.collateral\n ),\n _borrower\n );\n\n return abi.decode(responseData, (uint256));\n }\n\n /**\n * @notice Accepts a new loan using the TellerV2 lending protocol.\n * @param _bidId The id of the new loan.\n * @param _lender The address of the lender who will provide funds for the new loan.\n */\n function _acceptBid(uint256 _bidId, address _lender)\n internal\n virtual\n returns (bool)\n {\n // Approve the borrower's loan\n _forwardCall(\n abi.encodeWithSelector(ITellerV2.lenderAcceptBid.selector, _bidId),\n _lender\n );\n\n return true;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/TellerV2MarketForwarder_G3.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./interfaces/ITellerV2.sol\";\n\nimport \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/ITellerV2MarketForwarder.sol\";\nimport \"./interfaces/ILoanRepaymentCallbacks.sol\";\n\nimport \"./TellerV2MarketForwarder_G2.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\n\n/**\n * @dev Simple helper contract to forward an encoded function call to the TellerV2 contract. See {TellerV2Context}\n */\nabstract contract TellerV2MarketForwarder_G3 is TellerV2MarketForwarder_G2 {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _protocolAddress, address _marketRegistryAddress)\n TellerV2MarketForwarder_G2(_protocolAddress, _marketRegistryAddress)\n {}\n\n /**\n * @notice Accepts a new loan using the TellerV2 lending protocol.\n * @param _bidId The id of the new loan.\n * @param _lender The address of the lender who will provide funds for the new loan.\n */\n function _acceptBidWithRepaymentListener(\n uint256 _bidId,\n address _lender,\n address _listener\n ) internal virtual returns (bool) {\n // Approve the borrower's loan\n _forwardCall(\n abi.encodeWithSelector(ITellerV2.lenderAcceptBid.selector, _bidId),\n _lender\n );\n\n _forwardCall(\n abi.encodeWithSelector(\n ILoanRepaymentCallbacks.setRepaymentListenerForBid.selector,\n _bidId,\n _listener\n ),\n _lender\n );\n\n //ITellerV2(getTellerV2()).setRepaymentListenerForBid(_bidId, _listener);\n\n return true;\n }\n\n //a gap is inherited from g2 so this is actually not necessary going forwards ---leaving it to maintain upgradeability\n uint256[50] private __gap;\n}\n" + }, + "contracts/TellerV2Storage.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport { IMarketRegistry } from \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/IEscrowVault.sol\";\nimport \"./interfaces/IReputationManager.sol\";\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/ICollateralManager.sol\";\nimport { PaymentType, PaymentCycleType } from \"./libraries/V2Calculations.sol\";\nimport \"./interfaces/ILenderManager.sol\";\n\nenum BidState {\n NONEXISTENT,\n PENDING,\n CANCELLED,\n ACCEPTED,\n PAID,\n LIQUIDATED,\n CLOSED\n}\n\n/**\n * @notice Represents a total amount for a payment.\n * @param principal Amount that counts towards the principal.\n * @param interest Amount that counts toward interest.\n */\nstruct Payment {\n uint256 principal;\n uint256 interest;\n}\n\n/**\n * @notice Details about a loan request.\n * @param borrower Account address who is requesting a loan.\n * @param receiver Account address who will receive the loan amount.\n * @param lender Account address who accepted and funded the loan request.\n * @param marketplaceId ID of the marketplace the bid was submitted to.\n * @param metadataURI ID of off chain metadata to find additional information of the loan request.\n * @param loanDetails Struct of the specific loan details.\n * @param terms Struct of the loan request terms.\n * @param state Represents the current state of the loan.\n */\nstruct Bid {\n address borrower;\n address receiver;\n address lender; // if this is the LenderManager address, we use that .owner() as source of truth\n uint256 marketplaceId;\n bytes32 _metadataURI; // DEPRECATED\n LoanDetails loanDetails;\n Terms terms;\n BidState state;\n PaymentType paymentType;\n}\n\n/**\n * @notice Details about the loan.\n * @param lendingToken The token address for the loan.\n * @param principal The amount of tokens initially lent out.\n * @param totalRepaid Payment struct that represents the total principal and interest amount repaid.\n * @param timestamp Timestamp, in seconds, of when the bid was submitted by the borrower.\n * @param acceptedTimestamp Timestamp, in seconds, of when the bid was accepted by the lender.\n * @param lastRepaidTimestamp Timestamp, in seconds, of when the last payment was made\n * @param loanDuration The duration of the loan.\n */\nstruct LoanDetails {\n IERC20 lendingToken;\n uint256 principal;\n Payment totalRepaid;\n uint32 timestamp;\n uint32 acceptedTimestamp;\n uint32 lastRepaidTimestamp;\n uint32 loanDuration;\n}\n\n/**\n * @notice Information on the terms of a loan request\n * @param paymentCycleAmount Value of tokens expected to be repaid every payment cycle.\n * @param paymentCycle Duration, in seconds, of how often a payment must be made.\n * @param APR Annual percentage rating to be applied on repayments. (10000 == 100%)\n */\nstruct Terms {\n uint256 paymentCycleAmount;\n uint32 paymentCycle;\n uint16 APR;\n}\n\nabstract contract TellerV2Storage_G0 {\n /** Storage Variables */\n\n // Current number of bids.\n uint256 public bidId;\n\n // Mapping of bidId to bid information.\n mapping(uint256 => Bid) public bids;\n\n // Mapping of borrowers to borrower requests.\n mapping(address => uint256[]) public borrowerBids;\n\n // Mapping of volume filled by lenders.\n mapping(address => uint256) public __lenderVolumeFilled; // DEPRECIATED\n\n // Volume filled by all lenders.\n uint256 public __totalVolumeFilled; // DEPRECIATED\n\n // List of allowed lending tokens\n EnumerableSet.AddressSet internal __lendingTokensSet; // DEPRECATED\n\n IMarketRegistry public marketRegistry;\n IReputationManager public reputationManager;\n\n // Mapping of borrowers to borrower requests.\n mapping(address => EnumerableSet.UintSet) internal _borrowerBidsActive;\n\n mapping(uint256 => uint32) public bidDefaultDuration;\n mapping(uint256 => uint32) public bidExpirationTime;\n\n // Mapping of volume filled by lenders.\n // Asset address => Lender address => Volume amount\n mapping(address => mapping(address => uint256)) public lenderVolumeFilled;\n\n // Volume filled by all lenders.\n // Asset address => Volume amount\n mapping(address => uint256) public totalVolumeFilled;\n\n uint256 public version;\n\n // Mapping of metadataURIs by bidIds.\n // Bid Id => metadataURI string\n mapping(uint256 => string) public uris;\n}\n\nabstract contract TellerV2Storage_G1 is TellerV2Storage_G0 {\n // market ID => trusted forwarder\n mapping(uint256 => address) internal _trustedMarketForwarders;\n // trusted forwarder => set of pre-approved senders\n mapping(address => EnumerableSet.AddressSet)\n internal _approvedForwarderSenders;\n}\n\nabstract contract TellerV2Storage_G2 is TellerV2Storage_G1 {\n address public lenderCommitmentForwarder;\n}\n\nabstract contract TellerV2Storage_G3 is TellerV2Storage_G2 {\n ICollateralManager public collateralManager;\n}\n\nabstract contract TellerV2Storage_G4 is TellerV2Storage_G3 {\n // Address of the lender manager contract\n ILenderManager public lenderManager;\n // BidId to payment cycle type (custom or monthly)\n mapping(uint256 => PaymentCycleType) public bidPaymentCycleType;\n}\n\nabstract contract TellerV2Storage_G5 is TellerV2Storage_G4 {\n // Address of the lender manager contract\n IEscrowVault public escrowVault;\n}\n\nabstract contract TellerV2Storage_G6 is TellerV2Storage_G5 {\n mapping(uint256 => address) public repaymentListenerForBid;\n}\n\nabstract contract TellerV2Storage_G7 is TellerV2Storage_G6 {\n mapping(address => bool) public _reserved_G7_0 ;//pauserRoleBearer;\n bool public _reserved_G7_1; //liquidations paused\n}\n\nabstract contract TellerV2Storage is TellerV2Storage_G7 {}\n" + }, + "contracts/TLR.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract TLR is ERC20Votes, Ownable {\n uint224 private immutable MAX_SUPPLY;\n\n /**\n * @dev Sets the value of the `cap`. This value is immutable, it can only be\n * set once during construction.\n */\n constructor(uint224 _supplyCap, address tokenOwner)\n ERC20(\"Teller\", \"TLR\")\n ERC20Permit(\"Teller\")\n {\n require(_supplyCap > 0, \"ERC20Capped: cap is 0\");\n MAX_SUPPLY = _supplyCap;\n _transferOwnership(tokenOwner);\n }\n\n /**\n * @dev Max supply has been overridden to cap the token supply upon initialization of the contract\n * @dev See OpenZeppelin's implementation of ERC20Votes _mint() function\n */\n function _maxSupply() internal view override returns (uint224) {\n return MAX_SUPPLY;\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function mint(address account, uint256 amount) external onlyOwner {\n _mint(account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function burn(address account, uint256 amount) external onlyOwner {\n _burn(account, amount);\n }\n}\n" + }, + "contracts/type-imports.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n//SPDX-License-Identifier: MIT\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol\";\n\nimport \"@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol\";\n" + }, + "contracts/Types.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// A representation of an empty/uninitialized UUID.\nbytes32 constant EMPTY_UUID = 0;\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/solcInputs/e99b722e6618936643bdf6ab83e66ac0.json b/packages/contracts/deployments/polygon/solcInputs/e99b722e6618936643bdf6ab83e66ac0.json new file mode 100644 index 000000000..d24390625 --- /dev/null +++ b/packages/contracts/deployments/polygon/solcInputs/e99b722e6618936643bdf6ab83e66ac0.json @@ -0,0 +1,434 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol)\n\npragma solidity ^0.8.9;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Context variant with ERC2771 support.\n */\nabstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address private immutable _trustedForwarder;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address trustedForwarder) {\n _trustedForwarder = trustedForwarder;\n }\n\n function isTrustedForwarder(address forwarder) public view virtual returns (bool) {\n return forwarder == _trustedForwarder;\n }\n\n function _msgSender() internal view virtual override returns (address sender) {\n if (isTrustedForwarder(msg.sender)) {\n // The assembly code is more direct than the Solidity version using `abi.decode`.\n /// @solidity memory-safe-assembly\n assembly {\n sender := shr(96, calldataload(sub(calldatasize(), 20)))\n }\n } else {\n return super._msgSender();\n }\n }\n\n function _msgData() internal view virtual override returns (bytes calldata) {\n if (isTrustedForwarder(msg.sender)) {\n return msg.data[:msg.data.length - 20];\n } else {\n return super._msgData();\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155Upgradeable is IERC165Upgradeable {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes calldata data\n ) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 IERC20Upgradeable {\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 /**\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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721Upgradeable.sol\";\nimport \"./IERC721ReceiverUpgradeable.sol\";\nimport \"./extensions/IERC721MetadataUpgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../utils/StringsUpgradeable.sol\";\nimport \"../../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {\n using AddressUpgradeable for address;\n using StringsUpgradeable for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC721_init_unchained(name_, symbol_);\n }\n\n function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\n return\n interfaceId == type(IERC721Upgradeable).interfaceId ||\n interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _ownerOf(tokenId);\n require(owner != address(0), \"ERC721: invalid token ID\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not token owner or approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n _requireMinted(tokenId);\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n _safeTransfer(from, to, tokenId, data);\n }\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 * `data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\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 `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 _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n */\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n return _owners[tokenId];\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _ownerOf(tokenId) != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\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 _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n unchecked {\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\n // Given that tokens are minted one by one, it is impossible in practice that\n // this ever happens. Might change if we allow batch minting.\n // The ERC fails to describe this case.\n _balances[to] += 1;\n }\n\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId, 1);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n * This is an internal function that does not check if the sender is authorized to operate on the token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n owner = ERC721Upgradeable.ownerOf(tokenId);\n\n // Clear approvals\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // Cannot overflow, as that would require more tokens to be burned/transferred\n // out than the owner initially received through minting and transferring in.\n _balances[owner] -= 1;\n }\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId, 1);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId, 1);\n\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n // Clear approvals from the previous owner\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n // `from`'s balance is the number of token held, which is at least one before the current\n // transfer.\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n // all 2**256 token ids to be minted, which in practice is impossible.\n _balances[from] -= 1;\n _balances[to] += 1;\n }\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId, 1);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits an {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n * - When `from` is zero, the tokens will be minted for `to`.\n * - When `to` is zero, ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256, /* firstTokenId */\n uint256 batchSize\n ) internal virtual {\n if (batchSize > 1) {\n if (from != address(0)) {\n _balances[from] -= batchSize;\n }\n if (to != address(0)) {\n _balances[to] += batchSize;\n }\n }\n }\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n * - When `from` is zero, the tokens were minted for `to`.\n * - When `to` is zero, ``from``'s tokens were burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 firstTokenId,\n uint256 batchSize\n ) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721Upgradeable.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721ReceiverUpgradeable {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\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`.\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 /**\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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\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 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 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 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" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or 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 _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\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" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProofUpgradeable {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(\n bytes32[] calldata proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value for the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n return hashes[totalHashes - 1];\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proof.length - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value for the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n return hashes[totalHashes - 1];\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable {\n function __ERC165_init() internal onlyInitializing {\n }\n\n function __ERC165_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165Upgradeable).interfaceId;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.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 IERC165Upgradeable {\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" + }, + "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\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 return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\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\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\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 /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = MathUpgradeable.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSetUpgradeable {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (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 Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\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 the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\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" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (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 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 /**\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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or 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 _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\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" + }, + "@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" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\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 return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\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\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\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 /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "contracts/CollateralManager.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n// Libraries\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\n// Interfaces\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\";\nimport \"./interfaces/ICollateralManager.sol\";\nimport { Collateral, CollateralType, ICollateralEscrowV1 } from \"./interfaces/escrow/ICollateralEscrowV1.sol\";\nimport \"./interfaces/ITellerV2.sol\";\nimport \"./interfaces/IProtocolPausingManager.sol\";\nimport \"./interfaces/IHasProtocolPausingManager.sol\";\ncontract CollateralManager is OwnableUpgradeable, ICollateralManager {\n /* Storage */\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n ITellerV2 public tellerV2;\n address private collateralEscrowBeacon; // The address of the escrow contract beacon\n\n // bidIds -> collateralEscrow\n mapping(uint256 => address) public _escrows;\n // bidIds -> validated collateral info\n mapping(uint256 => CollateralInfo) internal _bidCollaterals;\n\n /**\n * Since collateralInfo is mapped (address assetAddress => Collateral) that means\n * that only a single tokenId per nft per loan can be collateralized.\n * Ex. Two bored apes cannot be used as collateral for a single loan.\n */\n struct CollateralInfo {\n EnumerableSetUpgradeable.AddressSet collateralAddresses;\n mapping(address => Collateral) collateralInfo;\n }\n\n /* Events */\n event CollateralEscrowDeployed(uint256 _bidId, address _collateralEscrow);\n event CollateralCommitted(\n uint256 _bidId,\n CollateralType _type,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId\n );\n event CollateralClaimed(uint256 _bidId);\n event CollateralDeposited(\n uint256 _bidId,\n CollateralType _type,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId\n );\n event CollateralWithdrawn(\n uint256 _bidId,\n CollateralType _type,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId,\n address _recipient\n );\n\n /* Modifiers */\n modifier onlyTellerV2() {\n require(_msgSender() == address(tellerV2), \"Sender not authorized\");\n _;\n }\n\n modifier onlyProtocolOwner() {\n\n address protocolOwner = OwnableUpgradeable(address(tellerV2)).owner();\n\n require(_msgSender() == protocolOwner, \"Sender not authorized\");\n _;\n }\n\n modifier whenProtocolNotPaused() { \n address pausingManager = IHasProtocolPausingManager( address(tellerV2) ).getProtocolPausingManager();\n\n require( IProtocolPausingManager(address(pausingManager)).protocolPaused() == false , \"Protocol is paused\");\n _;\n }\n\n /* External Functions */\n\n /**\n * @notice Initializes the collateral manager.\n * @param _collateralEscrowBeacon The address of the escrow implementation.\n * @param _tellerV2 The address of the protocol.\n */\n function initialize(address _collateralEscrowBeacon, address _tellerV2)\n external\n initializer\n {\n collateralEscrowBeacon = _collateralEscrowBeacon;\n tellerV2 = ITellerV2(_tellerV2);\n __Ownable_init_unchained();\n }\n\n /**\n * @notice Sets the address of the Beacon contract used for the collateral escrow contracts.\n * @param _collateralEscrowBeacon The address of the Beacon contract.\n */\n function setCollateralEscrowBeacon(address _collateralEscrowBeacon)\n external\n reinitializer(2)\n {\n collateralEscrowBeacon = _collateralEscrowBeacon;\n }\n\n /**\n * @notice Checks to see if a bid is backed by collateral.\n * @param _bidId The id of the bid to check.\n */\n\n function isBidCollateralBacked(uint256 _bidId)\n public\n virtual\n returns (bool)\n {\n return _bidCollaterals[_bidId].collateralAddresses.length() > 0;\n }\n\n /**\n * @notice Checks the validity of a borrower's multiple collateral balances and commits it to a bid.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral assets.\n * @return validation_ Boolean indicating if the collateral balances were validated.\n */\n function commitCollateral(\n uint256 _bidId,\n Collateral[] calldata _collateralInfo\n ) public onlyTellerV2 returns (bool validation_) {\n address borrower = tellerV2.getLoanBorrower(_bidId);\n require(borrower != address(0), \"Loan has no borrower\");\n (validation_, ) = checkBalances(borrower, _collateralInfo);\n\n //if the collateral info is valid, call commitCollateral for each one\n if (validation_) {\n for (uint256 i; i < _collateralInfo.length; i++) {\n Collateral memory info = _collateralInfo[i];\n _commitCollateral(_bidId, info);\n }\n }\n }\n\n /**\n * @notice Checks the validity of a borrower's collateral balance and commits it to a bid.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral asset.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function commitCollateral(\n uint256 _bidId,\n Collateral calldata _collateralInfo\n ) public onlyTellerV2 returns (bool validation_) {\n address borrower = tellerV2.getLoanBorrower(_bidId);\n require(borrower != address(0), \"Loan has no borrower\");\n validation_ = _checkBalance(borrower, _collateralInfo);\n if (validation_) {\n _commitCollateral(_bidId, _collateralInfo);\n }\n }\n\n /**\n * @notice Re-checks the validity of a borrower's collateral balance committed to a bid.\n * @param _bidId The id of the associated bid.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function revalidateCollateral(uint256 _bidId)\n external\n returns (bool validation_)\n {\n Collateral[] memory collateralInfos = getCollateralInfo(_bidId);\n address borrower = tellerV2.getLoanBorrower(_bidId);\n (validation_, ) = _checkBalances(borrower, collateralInfos, true);\n }\n\n /**\n * @notice Checks the validity of a borrower's multiple collateral balances.\n * @param _borrowerAddress The address of the borrower holding the collateral.\n * @param _collateralInfo Additional information about the collateral assets.\n */\n function checkBalances(\n address _borrowerAddress,\n Collateral[] calldata _collateralInfo\n ) public returns (bool validated_, bool[] memory checks_) {\n return _checkBalances(_borrowerAddress, _collateralInfo, false);\n }\n\n /**\n * @notice Deploys a new collateral escrow and deposits collateral.\n * @param _bidId The associated bidId of the collateral escrow.\n */\n function deployAndDeposit(uint256 _bidId) external onlyTellerV2 {\n if (isBidCollateralBacked(_bidId)) {\n //attempt deploy a new collateral escrow contract if there is not already one. Otherwise fetch it.\n (address proxyAddress, ) = _deployEscrow(_bidId);\n _escrows[_bidId] = proxyAddress;\n\n //for each bid collateral associated with this loan, deposit the collateral into escrow\n for (\n uint256 i;\n i < _bidCollaterals[_bidId].collateralAddresses.length();\n i++\n ) {\n _deposit(\n _bidId,\n _bidCollaterals[_bidId].collateralInfo[\n _bidCollaterals[_bidId].collateralAddresses.at(i)\n ]\n );\n }\n\n emit CollateralEscrowDeployed(_bidId, proxyAddress);\n }\n }\n\n /**\n * @notice Gets the address of a deployed escrow.\n * @notice _bidId The bidId to return the escrow for.\n * @return The address of the escrow.\n */\n function getEscrow(uint256 _bidId) external view returns (address) {\n return _escrows[_bidId];\n }\n\n /**\n * @notice Gets the collateral info for a given bid id.\n * @param _bidId The bidId to return the collateral info for.\n * @return infos_ The stored collateral info.\n */\n function getCollateralInfo(uint256 _bidId)\n public\n view\n returns (Collateral[] memory infos_)\n {\n CollateralInfo storage collateral = _bidCollaterals[_bidId];\n address[] memory collateralAddresses = collateral\n .collateralAddresses\n .values();\n infos_ = new Collateral[](collateralAddresses.length);\n for (uint256 i; i < collateralAddresses.length; i++) {\n infos_[i] = collateral.collateralInfo[collateralAddresses[i]];\n }\n }\n\n /**\n * @notice Gets the collateral asset amount for a given bid id on the TellerV2 contract.\n * @param _bidId The ID of a bid on TellerV2.\n * @param _collateralAddress An address used as collateral.\n * @return amount_ The amount of collateral of type _collateralAddress.\n */\n function getCollateralAmount(uint256 _bidId, address _collateralAddress)\n public\n view\n returns (uint256 amount_)\n {\n amount_ = _bidCollaterals[_bidId]\n .collateralInfo[_collateralAddress]\n ._amount;\n }\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid that has been successfully repaid.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function withdraw(uint256 _bidId) external whenProtocolNotPaused {\n BidState bidState = tellerV2.getBidState(_bidId);\n\n require(bidState == BidState.PAID, \"collateral cannot be withdrawn\");\n\n _withdraw(_bidId, tellerV2.getLoanBorrower(_bidId));\n\n emit CollateralClaimed(_bidId);\n }\n\n function withdrawDustTokens(\n uint256 _bidId, \n address _tokenAddress, \n uint256 _amount,\n address _recipientAddress\n ) external onlyProtocolOwner whenProtocolNotPaused {\n\n ICollateralEscrowV1(_escrows[_bidId]).withdrawDustTokens(\n _tokenAddress,\n _amount,\n _recipientAddress\n );\n }\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid that has been CLOSED after being defaulted.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function lenderClaimCollateral(uint256 _bidId) external onlyTellerV2 whenProtocolNotPaused {\n if (isBidCollateralBacked(_bidId)) {\n BidState bidState = tellerV2.getBidState(_bidId);\n\n require(\n bidState == BidState.CLOSED,\n \"Loan has not been liquidated\"\n );\n\n _withdraw(_bidId, tellerV2.getLoanLender(_bidId));\n emit CollateralClaimed(_bidId);\n }\n }\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid that has been CLOSED after being defaulted.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function lenderClaimCollateralWithRecipient(uint256 _bidId, address _collateralRecipient) external onlyTellerV2 whenProtocolNotPaused {\n if (isBidCollateralBacked(_bidId)) {\n BidState bidState = tellerV2.getBidState(_bidId);\n\n require(\n bidState == BidState.CLOSED,\n \"Loan has not been liquidated\"\n );\n\n _withdraw(_bidId, _collateralRecipient);\n emit CollateralClaimed(_bidId);\n }\n }\n\n /**\n * @notice Sends the deposited collateral to a liquidator of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n * @param _liquidatorAddress The address of the liquidator to send the collateral to.\n */\n function liquidateCollateral(uint256 _bidId, address _liquidatorAddress)\n external\n onlyTellerV2\n whenProtocolNotPaused\n {\n if (isBidCollateralBacked(_bidId)) {\n BidState bidState = tellerV2.getBidState(_bidId);\n require(\n bidState == BidState.LIQUIDATED,\n \"Loan has not been liquidated\"\n );\n _withdraw(_bidId, _liquidatorAddress);\n }\n }\n\n /* Internal Functions */\n\n /**\n * @notice Deploys a new collateral escrow.\n * @param _bidId The associated bidId of the collateral escrow.\n */\n function _deployEscrow(uint256 _bidId)\n internal\n virtual\n returns (address proxyAddress_, address borrower_)\n {\n proxyAddress_ = _escrows[_bidId];\n // Get bid info\n borrower_ = tellerV2.getLoanBorrower(_bidId);\n if (proxyAddress_ == address(0)) {\n require(borrower_ != address(0), \"Bid does not exist\");\n\n BeaconProxy proxy = new BeaconProxy(\n collateralEscrowBeacon,\n abi.encodeWithSelector(\n ICollateralEscrowV1.initialize.selector,\n _bidId\n )\n );\n proxyAddress_ = address(proxy);\n }\n }\n\n /*\n * @notice Deploys a new collateral escrow contract. Deposits collateral into a collateral escrow.\n * @param _bidId The associated bidId of the collateral escrow.\n * @param collateralInfo The collateral info to deposit.\n\n */\n function _deposit(uint256 _bidId, Collateral memory collateralInfo)\n internal\n virtual\n {\n require(collateralInfo._amount > 0, \"Collateral not validated\");\n (address escrowAddress, address borrower) = _deployEscrow(_bidId);\n ICollateralEscrowV1 collateralEscrow = ICollateralEscrowV1(\n escrowAddress\n );\n // Pull collateral from borrower & deposit into escrow\n if (collateralInfo._collateralType == CollateralType.ERC20) {\n IERC20Upgradeable(collateralInfo._collateralAddress).transferFrom(\n borrower,\n address(this),\n collateralInfo._amount\n );\n IERC20Upgradeable(collateralInfo._collateralAddress).approve(\n escrowAddress,\n collateralInfo._amount\n );\n collateralEscrow.depositAsset(\n CollateralType.ERC20,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n 0\n );\n } else if (collateralInfo._collateralType == CollateralType.ERC721) {\n IERC721Upgradeable(collateralInfo._collateralAddress).transferFrom(\n borrower,\n address(this),\n collateralInfo._tokenId\n );\n IERC721Upgradeable(collateralInfo._collateralAddress).approve(\n escrowAddress,\n collateralInfo._tokenId\n );\n collateralEscrow.depositAsset(\n CollateralType.ERC721,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n collateralInfo._tokenId\n );\n } else if (collateralInfo._collateralType == CollateralType.ERC1155) {\n bytes memory data;\n IERC1155Upgradeable(collateralInfo._collateralAddress)\n .safeTransferFrom(\n borrower,\n address(this),\n collateralInfo._tokenId,\n collateralInfo._amount,\n data\n );\n IERC1155Upgradeable(collateralInfo._collateralAddress)\n .setApprovalForAll(escrowAddress, true);\n collateralEscrow.depositAsset(\n CollateralType.ERC1155,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n collateralInfo._tokenId\n );\n } else {\n revert(\"Unexpected collateral type\");\n }\n emit CollateralDeposited(\n _bidId,\n collateralInfo._collateralType,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n collateralInfo._tokenId\n );\n }\n\n /**\n * @notice Withdraws collateral to a given receiver's address.\n * @param _bidId The id of the bid to withdraw collateral for.\n * @param _receiver The address to withdraw the collateral to.\n */\n function _withdraw(uint256 _bidId, address _receiver) internal virtual {\n for (\n uint256 i;\n i < _bidCollaterals[_bidId].collateralAddresses.length();\n i++\n ) {\n // Get collateral info\n Collateral storage collateralInfo = _bidCollaterals[_bidId]\n .collateralInfo[\n _bidCollaterals[_bidId].collateralAddresses.at(i)\n ];\n // Withdraw collateral from escrow and send it to bid lender\n ICollateralEscrowV1(_escrows[_bidId]).withdraw(\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n _receiver\n );\n emit CollateralWithdrawn(\n _bidId,\n collateralInfo._collateralType,\n collateralInfo._collateralAddress,\n collateralInfo._amount,\n collateralInfo._tokenId,\n _receiver\n );\n }\n }\n\n /**\n * @notice Checks the validity of a borrower's collateral balance and commits it to a bid.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral asset.\n */\n function _commitCollateral(\n uint256 _bidId,\n Collateral memory _collateralInfo\n ) internal virtual {\n CollateralInfo storage collateral = _bidCollaterals[_bidId];\n\n require(\n !collateral.collateralAddresses.contains(\n _collateralInfo._collateralAddress\n ),\n \"Cannot commit multiple collateral with the same address\"\n );\n require(\n _collateralInfo._collateralType != CollateralType.ERC721 ||\n _collateralInfo._amount == 1,\n \"ERC721 collateral must have amount of 1\"\n );\n\n collateral.collateralAddresses.add(_collateralInfo._collateralAddress);\n collateral.collateralInfo[\n _collateralInfo._collateralAddress\n ] = _collateralInfo;\n emit CollateralCommitted(\n _bidId,\n _collateralInfo._collateralType,\n _collateralInfo._collateralAddress,\n _collateralInfo._amount,\n _collateralInfo._tokenId\n );\n }\n\n /**\n * @notice Checks the validity of a borrower's multiple collateral balances.\n * @param _borrowerAddress The address of the borrower holding the collateral.\n * @param _collateralInfo Additional information about the collateral assets.\n * @param _shortCircut if true, will return immediately until an invalid balance\n */\n function _checkBalances(\n address _borrowerAddress,\n Collateral[] memory _collateralInfo,\n bool _shortCircut\n ) internal virtual returns (bool validated_, bool[] memory checks_) {\n checks_ = new bool[](_collateralInfo.length);\n validated_ = true;\n for (uint256 i; i < _collateralInfo.length; i++) {\n bool isValidated = _checkBalance(\n _borrowerAddress,\n _collateralInfo[i]\n );\n checks_[i] = isValidated;\n if (!isValidated) {\n validated_ = false;\n //if short circuit is true, return on the first invalid balance to save execution cycles. Values of checks[] will be invalid/undetermined if shortcircuit is true.\n if (_shortCircut) {\n return (validated_, checks_);\n }\n }\n }\n }\n\n /**\n * @notice Checks the validity of a borrower's single collateral balance.\n * @param _borrowerAddress The address of the borrower holding the collateral.\n * @param _collateralInfo Additional information about the collateral asset.\n * @return validation_ Boolean indicating if the collateral balances were validated.\n */\n function _checkBalance(\n address _borrowerAddress,\n Collateral memory _collateralInfo\n ) internal virtual returns (bool) {\n CollateralType collateralType = _collateralInfo._collateralType;\n\n if (collateralType == CollateralType.ERC20) {\n return\n _collateralInfo._amount <=\n IERC20Upgradeable(_collateralInfo._collateralAddress).balanceOf(\n _borrowerAddress\n );\n } else if (collateralType == CollateralType.ERC721) {\n return\n _borrowerAddress ==\n IERC721Upgradeable(_collateralInfo._collateralAddress).ownerOf(\n _collateralInfo._tokenId\n );\n } else if (collateralType == CollateralType.ERC1155) {\n return\n _collateralInfo._amount <=\n IERC1155Upgradeable(_collateralInfo._collateralAddress)\n .balanceOf(_borrowerAddress, _collateralInfo._tokenId);\n } else {\n return false;\n }\n }\n\n // On NFT Received handlers\n\n function onERC721Received(address, address, uint256, bytes calldata)\n external\n pure\n returns (bytes4)\n {\n return\n bytes4(\n keccak256(\"onERC721Received(address,address,uint256,bytes)\")\n );\n }\n\n function onERC1155Received(\n address,\n address,\n uint256 id,\n uint256 value,\n bytes calldata\n ) external returns (bytes4) {\n return\n bytes4(\n keccak256(\n \"onERC1155Received(address,address,uint256,uint256,bytes)\"\n )\n );\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] calldata _ids,\n uint256[] calldata _values,\n bytes calldata\n ) external returns (bytes4) {\n require(\n _ids.length == 1,\n \"Only allowed one asset batch transfer per transaction.\"\n );\n return\n bytes4(\n keccak256(\n \"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"\n )\n );\n }\n}\n" + }, + "contracts/EAS/TellerAS.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"../Types.sol\";\nimport \"../interfaces/IEAS.sol\";\nimport \"../interfaces/IASRegistry.sol\";\n\n/**\n * @title TellerAS - Teller Attestation Service - based on EAS - Ethereum Attestation Service\n */\ncontract TellerAS is IEAS {\n error AccessDenied();\n error AlreadyRevoked();\n error InvalidAttestation();\n error InvalidExpirationTime();\n error InvalidOffset();\n error InvalidRegistry();\n error InvalidSchema();\n error InvalidVerifier();\n error NotFound();\n error NotPayable();\n\n string public constant VERSION = \"0.8\";\n\n // A terminator used when concatenating and hashing multiple fields.\n string private constant HASH_TERMINATOR = \"@\";\n\n // The AS global registry.\n IASRegistry private immutable _asRegistry;\n\n // The EIP712 verifier used to verify signed attestations.\n IEASEIP712Verifier private immutable _eip712Verifier;\n\n // A mapping between attestations and their related attestations.\n mapping(bytes32 => bytes32[]) private _relatedAttestations;\n\n // A mapping between an account and its received attestations.\n mapping(address => mapping(bytes32 => bytes32[]))\n private _receivedAttestations;\n\n // A mapping between an account and its sent attestations.\n mapping(address => mapping(bytes32 => bytes32[])) private _sentAttestations;\n\n // A mapping between a schema and its attestations.\n mapping(bytes32 => bytes32[]) private _schemaAttestations;\n\n // The global mapping between attestations and their UUIDs.\n mapping(bytes32 => Attestation) private _db;\n\n // The global counter for the total number of attestations.\n uint256 private _attestationsCount;\n\n bytes32 private _lastUUID;\n\n /**\n * @dev Creates a new EAS instance.\n *\n * @param registry The address of the global AS registry.\n * @param verifier The address of the EIP712 verifier.\n */\n constructor(IASRegistry registry, IEASEIP712Verifier verifier) {\n if (address(registry) == address(0x0)) {\n revert InvalidRegistry();\n }\n\n if (address(verifier) == address(0x0)) {\n revert InvalidVerifier();\n }\n\n _asRegistry = registry;\n _eip712Verifier = verifier;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getASRegistry() external view override returns (IASRegistry) {\n return _asRegistry;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getEIP712Verifier()\n external\n view\n override\n returns (IEASEIP712Verifier)\n {\n return _eip712Verifier;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getAttestationsCount() external view override returns (uint256) {\n return _attestationsCount;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data\n ) public payable virtual override returns (bytes32) {\n return\n _attest(\n recipient,\n schema,\n expirationTime,\n refUUID,\n data,\n msg.sender\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function attestByDelegation(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public payable virtual override returns (bytes32) {\n _eip712Verifier.attest(\n recipient,\n schema,\n expirationTime,\n refUUID,\n data,\n attester,\n v,\n r,\n s\n );\n\n return\n _attest(recipient, schema, expirationTime, refUUID, data, attester);\n }\n\n /**\n * @inheritdoc IEAS\n */\n function revoke(bytes32 uuid) public virtual override {\n return _revoke(uuid, msg.sender);\n }\n\n /**\n * @inheritdoc IEAS\n */\n function revokeByDelegation(\n bytes32 uuid,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual override {\n _eip712Verifier.revoke(uuid, attester, v, r, s);\n\n _revoke(uuid, attester);\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getAttestation(bytes32 uuid)\n external\n view\n override\n returns (Attestation memory)\n {\n return _db[uuid];\n }\n\n /**\n * @inheritdoc IEAS\n */\n function isAttestationValid(bytes32 uuid)\n public\n view\n override\n returns (bool)\n {\n return _db[uuid].uuid != 0;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function isAttestationActive(bytes32 uuid)\n public\n view\n virtual\n override\n returns (bool)\n {\n return\n isAttestationValid(uuid) &&\n _db[uuid].expirationTime >= block.timestamp &&\n _db[uuid].revocationTime == 0;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getReceivedAttestationUUIDs(\n address recipient,\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view override returns (bytes32[] memory) {\n return\n _sliceUUIDs(\n _receivedAttestations[recipient][schema],\n start,\n length,\n reverseOrder\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getReceivedAttestationUUIDsCount(address recipient, bytes32 schema)\n external\n view\n override\n returns (uint256)\n {\n return _receivedAttestations[recipient][schema].length;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getSentAttestationUUIDs(\n address attester,\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view override returns (bytes32[] memory) {\n return\n _sliceUUIDs(\n _sentAttestations[attester][schema],\n start,\n length,\n reverseOrder\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getSentAttestationUUIDsCount(address recipient, bytes32 schema)\n external\n view\n override\n returns (uint256)\n {\n return _sentAttestations[recipient][schema].length;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getRelatedAttestationUUIDs(\n bytes32 uuid,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view override returns (bytes32[] memory) {\n return\n _sliceUUIDs(\n _relatedAttestations[uuid],\n start,\n length,\n reverseOrder\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getRelatedAttestationUUIDsCount(bytes32 uuid)\n external\n view\n override\n returns (uint256)\n {\n return _relatedAttestations[uuid].length;\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getSchemaAttestationUUIDs(\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view override returns (bytes32[] memory) {\n return\n _sliceUUIDs(\n _schemaAttestations[schema],\n start,\n length,\n reverseOrder\n );\n }\n\n /**\n * @inheritdoc IEAS\n */\n function getSchemaAttestationUUIDsCount(bytes32 schema)\n external\n view\n override\n returns (uint256)\n {\n return _schemaAttestations[schema].length;\n }\n\n /**\n * @dev Attests to a specific AS.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param expirationTime The expiration time of the attestation.\n * @param refUUID An optional related attestation's UUID.\n * @param data Additional custom data.\n * @param attester The attesting account.\n *\n * @return The UUID of the new attestation.\n */\n function _attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester\n ) private returns (bytes32) {\n if (expirationTime <= block.timestamp) {\n revert InvalidExpirationTime();\n }\n\n IASRegistry.ASRecord memory asRecord = _asRegistry.getAS(schema);\n if (asRecord.uuid == EMPTY_UUID) {\n revert InvalidSchema();\n }\n\n IASResolver resolver = asRecord.resolver;\n if (address(resolver) != address(0x0)) {\n if (msg.value != 0 && !resolver.isPayable()) {\n revert NotPayable();\n }\n\n if (\n !resolver.resolve{ value: msg.value }(\n recipient,\n asRecord.schema,\n data,\n expirationTime,\n attester\n )\n ) {\n revert InvalidAttestation();\n }\n }\n\n Attestation memory attestation = Attestation({\n uuid: EMPTY_UUID,\n schema: schema,\n recipient: recipient,\n attester: attester,\n time: block.timestamp,\n expirationTime: expirationTime,\n revocationTime: 0,\n refUUID: refUUID,\n data: data\n });\n\n _lastUUID = _getUUID(attestation);\n attestation.uuid = _lastUUID;\n\n _receivedAttestations[recipient][schema].push(_lastUUID);\n _sentAttestations[attester][schema].push(_lastUUID);\n _schemaAttestations[schema].push(_lastUUID);\n\n _db[_lastUUID] = attestation;\n _attestationsCount++;\n\n if (refUUID != 0) {\n if (!isAttestationValid(refUUID)) {\n revert NotFound();\n }\n\n _relatedAttestations[refUUID].push(_lastUUID);\n }\n\n emit Attested(recipient, attester, _lastUUID, schema);\n\n return _lastUUID;\n }\n\n function getLastUUID() external view returns (bytes32) {\n return _lastUUID;\n }\n\n /**\n * @dev Revokes an existing attestation to a specific AS.\n *\n * @param uuid The UUID of the attestation to revoke.\n * @param attester The attesting account.\n */\n function _revoke(bytes32 uuid, address attester) private {\n Attestation storage attestation = _db[uuid];\n if (attestation.uuid == EMPTY_UUID) {\n revert NotFound();\n }\n\n if (attestation.attester != attester) {\n revert AccessDenied();\n }\n\n if (attestation.revocationTime != 0) {\n revert AlreadyRevoked();\n }\n\n attestation.revocationTime = block.timestamp;\n\n emit Revoked(attestation.recipient, attester, uuid, attestation.schema);\n }\n\n /**\n * @dev Calculates a UUID for a given attestation.\n *\n * @param attestation The input attestation.\n *\n * @return Attestation UUID.\n */\n function _getUUID(Attestation memory attestation)\n private\n view\n returns (bytes32)\n {\n return\n keccak256(\n abi.encodePacked(\n attestation.schema,\n attestation.recipient,\n attestation.attester,\n attestation.time,\n attestation.expirationTime,\n attestation.data,\n HASH_TERMINATOR,\n _attestationsCount\n )\n );\n }\n\n /**\n * @dev Returns a slice in an array of attestation UUIDs.\n *\n * @param uuids The array of attestation UUIDs.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function _sliceUUIDs(\n bytes32[] memory uuids,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) private pure returns (bytes32[] memory) {\n uint256 attestationsLength = uuids.length;\n if (attestationsLength == 0) {\n return new bytes32[](0);\n }\n\n if (start >= attestationsLength) {\n revert InvalidOffset();\n }\n\n uint256 len = length;\n if (attestationsLength < start + length) {\n len = attestationsLength - start;\n }\n\n bytes32[] memory res = new bytes32[](len);\n\n for (uint256 i = 0; i < len; ++i) {\n res[i] = uuids[\n reverseOrder ? attestationsLength - (start + i + 1) : start + i\n ];\n }\n\n return res;\n }\n}\n" + }, + "contracts/EAS/TellerASResolver.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"../interfaces/IASResolver.sol\";\n\n/**\n * @title A base resolver contract\n */\nabstract contract TellerASResolver is IASResolver {\n error NotPayable();\n\n function isPayable() public pure virtual override returns (bool) {\n return false;\n }\n\n receive() external payable virtual {\n if (!isPayable()) {\n revert NotPayable();\n }\n }\n}\n" + }, + "contracts/ERC2771ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (metatx/ERC2771Context.sol)\n\npragma solidity ^0.8.9;\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Context variant with ERC2771 support.\n * @dev This is modified from the OZ library to remove the gap of storage variables at the end.\n */\nabstract contract ERC2771ContextUpgradeable is\n Initializable,\n ContextUpgradeable\n{\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address private immutable _trustedForwarder;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address trustedForwarder) {\n _trustedForwarder = trustedForwarder;\n }\n\n function isTrustedForwarder(address forwarder)\n public\n view\n virtual\n returns (bool)\n {\n return forwarder == _trustedForwarder;\n }\n\n function _msgSender()\n internal\n view\n virtual\n override\n returns (address sender)\n {\n if (isTrustedForwarder(msg.sender)) {\n // The assembly code is more direct than the Solidity version using `abi.decode`.\n assembly {\n sender := shr(96, calldataload(sub(calldatasize(), 20)))\n }\n } else {\n return super._msgSender();\n }\n }\n\n function _msgData()\n internal\n view\n virtual\n override\n returns (bytes calldata)\n {\n if (isTrustedForwarder(msg.sender)) {\n return msg.data[:msg.data.length - 20];\n } else {\n return super._msgData();\n }\n }\n}\n" + }, + "contracts/interfaces/aave/DataTypes.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nlibrary DataTypes {\n struct ReserveData {\n //stores the reserve configuration\n ReserveConfigurationMap configuration;\n //the liquidity index. Expressed in ray\n uint128 liquidityIndex;\n //the current supply rate. Expressed in ray\n uint128 currentLiquidityRate;\n //variable borrow index. Expressed in ray\n uint128 variableBorrowIndex;\n //the current variable borrow rate. Expressed in ray\n uint128 currentVariableBorrowRate;\n //the current stable borrow rate. Expressed in ray\n uint128 currentStableBorrowRate;\n //timestamp of last update\n uint40 lastUpdateTimestamp;\n //the id of the reserve. Represents the position in the list of the active reserves\n uint16 id;\n //aToken address\n address aTokenAddress;\n //stableDebtToken address\n address stableDebtTokenAddress;\n //variableDebtToken address\n address variableDebtTokenAddress;\n //address of the interest rate strategy\n address interestRateStrategyAddress;\n //the current treasury balance, scaled\n uint128 accruedToTreasury;\n //the outstanding unbacked aTokens minted through the bridging feature\n uint128 unbacked;\n //the outstanding debt borrowed against this asset in isolation mode\n uint128 isolationModeTotalDebt;\n }\n\n struct ReserveConfigurationMap {\n //bit 0-15: LTV\n //bit 16-31: Liq. threshold\n //bit 32-47: Liq. bonus\n //bit 48-55: Decimals\n //bit 56: reserve is active\n //bit 57: reserve is frozen\n //bit 58: borrowing is enabled\n //bit 59: stable rate borrowing enabled\n //bit 60: asset is paused\n //bit 61: borrowing in isolation mode is enabled\n //bit 62: siloed borrowing enabled\n //bit 63: flashloaning enabled\n //bit 64-79: reserve factor\n //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap\n //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap\n //bit 152-167 liquidation protocol fee\n //bit 168-175 eMode category\n //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled\n //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals\n //bit 252-255 unused\n\n uint256 data;\n }\n\n struct UserConfigurationMap {\n /**\n * @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset.\n * The first bit indicates if an asset is used as collateral by the user, the second whether an\n * asset is borrowed by the user.\n */\n uint256 data;\n }\n\n struct EModeCategory {\n // each eMode category has a custom ltv and liquidation threshold\n uint16 ltv;\n uint16 liquidationThreshold;\n uint16 liquidationBonus;\n // each eMode category may or may not have a custom oracle to override the individual assets price oracles\n address priceSource;\n string label;\n }\n\n enum InterestRateMode {\n NONE,\n STABLE,\n VARIABLE\n }\n\n struct ReserveCache {\n uint256 currScaledVariableDebt;\n uint256 nextScaledVariableDebt;\n uint256 currPrincipalStableDebt;\n uint256 currAvgStableBorrowRate;\n uint256 currTotalStableDebt;\n uint256 nextAvgStableBorrowRate;\n uint256 nextTotalStableDebt;\n uint256 currLiquidityIndex;\n uint256 nextLiquidityIndex;\n uint256 currVariableBorrowIndex;\n uint256 nextVariableBorrowIndex;\n uint256 currLiquidityRate;\n uint256 currVariableBorrowRate;\n uint256 reserveFactor;\n ReserveConfigurationMap reserveConfiguration;\n address aTokenAddress;\n address stableDebtTokenAddress;\n address variableDebtTokenAddress;\n uint40 reserveLastUpdateTimestamp;\n uint40 stableDebtLastUpdateTimestamp;\n }\n\n struct ExecuteLiquidationCallParams {\n uint256 reservesCount;\n uint256 debtToCover;\n address collateralAsset;\n address debtAsset;\n address user;\n bool receiveAToken;\n address priceOracle;\n uint8 userEModeCategory;\n address priceOracleSentinel;\n }\n\n struct ExecuteSupplyParams {\n address asset;\n uint256 amount;\n address onBehalfOf;\n uint16 referralCode;\n }\n\n struct ExecuteBorrowParams {\n address asset;\n address user;\n address onBehalfOf;\n uint256 amount;\n InterestRateMode interestRateMode;\n uint16 referralCode;\n bool releaseUnderlying;\n uint256 maxStableRateBorrowSizePercent;\n uint256 reservesCount;\n address oracle;\n uint8 userEModeCategory;\n address priceOracleSentinel;\n }\n\n struct ExecuteRepayParams {\n address asset;\n uint256 amount;\n InterestRateMode interestRateMode;\n address onBehalfOf;\n bool useATokens;\n }\n\n struct ExecuteWithdrawParams {\n address asset;\n uint256 amount;\n address to;\n uint256 reservesCount;\n address oracle;\n uint8 userEModeCategory;\n }\n\n struct ExecuteSetUserEModeParams {\n uint256 reservesCount;\n address oracle;\n uint8 categoryId;\n }\n\n struct FinalizeTransferParams {\n address asset;\n address from;\n address to;\n uint256 amount;\n uint256 balanceFromBefore;\n uint256 balanceToBefore;\n uint256 reservesCount;\n address oracle;\n uint8 fromEModeCategory;\n }\n\n struct FlashloanParams {\n address receiverAddress;\n address[] assets;\n uint256[] amounts;\n uint256[] interestRateModes;\n address onBehalfOf;\n bytes params;\n uint16 referralCode;\n uint256 flashLoanPremiumToProtocol;\n uint256 flashLoanPremiumTotal;\n uint256 maxStableRateBorrowSizePercent;\n uint256 reservesCount;\n address addressesProvider;\n uint8 userEModeCategory;\n bool isAuthorizedFlashBorrower;\n }\n\n struct FlashloanSimpleParams {\n address receiverAddress;\n address asset;\n uint256 amount;\n bytes params;\n uint16 referralCode;\n uint256 flashLoanPremiumToProtocol;\n uint256 flashLoanPremiumTotal;\n }\n\n struct FlashLoanRepaymentParams {\n uint256 amount;\n uint256 totalPremium;\n uint256 flashLoanPremiumToProtocol;\n address asset;\n address receiverAddress;\n uint16 referralCode;\n }\n\n struct CalculateUserAccountDataParams {\n UserConfigurationMap userConfig;\n uint256 reservesCount;\n address user;\n address oracle;\n uint8 userEModeCategory;\n }\n\n struct ValidateBorrowParams {\n ReserveCache reserveCache;\n UserConfigurationMap userConfig;\n address asset;\n address userAddress;\n uint256 amount;\n InterestRateMode interestRateMode;\n uint256 maxStableLoanPercent;\n uint256 reservesCount;\n address oracle;\n uint8 userEModeCategory;\n address priceOracleSentinel;\n bool isolationModeActive;\n address isolationModeCollateralAddress;\n uint256 isolationModeDebtCeiling;\n }\n\n struct ValidateLiquidationCallParams {\n ReserveCache debtReserveCache;\n uint256 totalDebt;\n uint256 healthFactor;\n address priceOracleSentinel;\n }\n\n struct CalculateInterestRatesParams {\n uint256 unbacked;\n uint256 liquidityAdded;\n uint256 liquidityTaken;\n uint256 totalStableDebt;\n uint256 totalVariableDebt;\n uint256 averageStableBorrowRate;\n uint256 reserveFactor;\n address reserve;\n address aToken;\n }\n\n struct InitReserveParams {\n address asset;\n address aTokenAddress;\n address stableDebtAddress;\n address variableDebtAddress;\n address interestRateStrategyAddress;\n uint16 reservesCount;\n uint16 maxNumberReserves;\n }\n}\n" + }, + "contracts/interfaces/aave/IFlashLoanSimpleReceiver.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.0;\n\nimport { IPoolAddressesProvider } from \"./IPoolAddressesProvider.sol\";\nimport { IPool } from \"./IPool.sol\";\n\n/**\n * @title IFlashLoanSimpleReceiver\n * @author Aave\n * @notice Defines the basic interface of a flashloan-receiver contract.\n * @dev Implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n */\ninterface IFlashLoanSimpleReceiver {\n /**\n * @notice Executes an operation after receiving the flash-borrowed asset\n * @dev Ensure that the contract can return the debt + premium, e.g., has\n * enough funds to repay and has approved the Pool to pull the total amount\n * @param asset The address of the flash-borrowed asset\n * @param amount The amount of the flash-borrowed asset\n * @param premium The fee of the flash-borrowed asset\n * @param initiator The address of the flashloan initiator\n * @param params The byte-encoded params passed when initiating the flashloan\n * @return True if the execution of the operation succeeds, false otherwise\n */\n function executeOperation(\n address asset,\n uint256 amount,\n uint256 premium,\n address initiator,\n bytes calldata params\n ) external returns (bool);\n\n function ADDRESSES_PROVIDER()\n external\n view\n returns (IPoolAddressesProvider);\n\n function POOL() external view returns (IPool);\n}\n" + }, + "contracts/interfaces/aave/IPool.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.0;\n\nimport { IPoolAddressesProvider } from \"./IPoolAddressesProvider.sol\";\nimport { DataTypes } from \"./DataTypes.sol\";\n\n/**\n * @title IPool\n * @author Aave\n * @notice Defines the basic interface for an Aave Pool.\n */\ninterface IPool {\n /**\n * @dev Emitted on mintUnbacked()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address initiating the supply\n * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens\n * @param amount The amount of supplied assets\n * @param referralCode The referral code used\n */\n event MintUnbacked(\n address indexed reserve,\n address user,\n address indexed onBehalfOf,\n uint256 amount,\n uint16 indexed referralCode\n );\n\n /**\n * @dev Emitted on backUnbacked()\n * @param reserve The address of the underlying asset of the reserve\n * @param backer The address paying for the backing\n * @param amount The amount added as backing\n * @param fee The amount paid in fees\n */\n event BackUnbacked(\n address indexed reserve,\n address indexed backer,\n uint256 amount,\n uint256 fee\n );\n\n /**\n * @dev Emitted on supply()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address initiating the supply\n * @param onBehalfOf The beneficiary of the supply, receiving the aTokens\n * @param amount The amount supplied\n * @param referralCode The referral code used\n */\n event Supply(\n address indexed reserve,\n address user,\n address indexed onBehalfOf,\n uint256 amount,\n uint16 indexed referralCode\n );\n\n /**\n * @dev Emitted on withdraw()\n * @param reserve The address of the underlying asset being withdrawn\n * @param user The address initiating the withdrawal, owner of aTokens\n * @param to The address that will receive the underlying\n * @param amount The amount to be withdrawn\n */\n event Withdraw(\n address indexed reserve,\n address indexed user,\n address indexed to,\n uint256 amount\n );\n\n /**\n * @dev Emitted on borrow() and flashLoan() when debt needs to be opened\n * @param reserve The address of the underlying asset being borrowed\n * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just\n * initiator of the transaction on flashLoan()\n * @param onBehalfOf The address that will be getting the debt\n * @param amount The amount borrowed out\n * @param interestRateMode The rate mode: 1 for Stable, 2 for Variable\n * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray\n * @param referralCode The referral code used\n */\n event Borrow(\n address indexed reserve,\n address user,\n address indexed onBehalfOf,\n uint256 amount,\n DataTypes.InterestRateMode interestRateMode,\n uint256 borrowRate,\n uint16 indexed referralCode\n );\n\n /**\n * @dev Emitted on repay()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The beneficiary of the repayment, getting his debt reduced\n * @param repayer The address of the user initiating the repay(), providing the funds\n * @param amount The amount repaid\n * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly\n */\n event Repay(\n address indexed reserve,\n address indexed user,\n address indexed repayer,\n uint256 amount,\n bool useATokens\n );\n\n /**\n * @dev Emitted on swapBorrowRateMode()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user swapping his rate mode\n * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable\n */\n event SwapBorrowRateMode(\n address indexed reserve,\n address indexed user,\n DataTypes.InterestRateMode interestRateMode\n );\n\n /**\n * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets\n * @param asset The address of the underlying asset of the reserve\n * @param totalDebt The total isolation mode debt for the reserve\n */\n event IsolationModeTotalDebtUpdated(\n address indexed asset,\n uint256 totalDebt\n );\n\n /**\n * @dev Emitted when the user selects a certain asset category for eMode\n * @param user The address of the user\n * @param categoryId The category id\n */\n event UserEModeSet(address indexed user, uint8 categoryId);\n\n /**\n * @dev Emitted on setUserUseReserveAsCollateral()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user enabling the usage as collateral\n */\n event ReserveUsedAsCollateralEnabled(\n address indexed reserve,\n address indexed user\n );\n\n /**\n * @dev Emitted on setUserUseReserveAsCollateral()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user enabling the usage as collateral\n */\n event ReserveUsedAsCollateralDisabled(\n address indexed reserve,\n address indexed user\n );\n\n /**\n * @dev Emitted on rebalanceStableBorrowRate()\n * @param reserve The address of the underlying asset of the reserve\n * @param user The address of the user for which the rebalance has been executed\n */\n event RebalanceStableBorrowRate(\n address indexed reserve,\n address indexed user\n );\n\n /**\n * @dev Emitted on flashLoan()\n * @param target The address of the flash loan receiver contract\n * @param initiator The address initiating the flash loan\n * @param asset The address of the asset being flash borrowed\n * @param amount The amount flash borrowed\n * @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt\n * @param premium The fee flash borrowed\n * @param referralCode The referral code used\n */\n event FlashLoan(\n address indexed target,\n address initiator,\n address indexed asset,\n uint256 amount,\n DataTypes.InterestRateMode interestRateMode,\n uint256 premium,\n uint16 indexed referralCode\n );\n\n /**\n * @dev Emitted when a borrower is liquidated.\n * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\n * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\n * @param user The address of the borrower getting liquidated\n * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\n * @param liquidatedCollateralAmount The amount of collateral received by the liquidator\n * @param liquidator The address of the liquidator\n * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants\n * to receive the underlying collateral asset directly\n */\n event LiquidationCall(\n address indexed collateralAsset,\n address indexed debtAsset,\n address indexed user,\n uint256 debtToCover,\n uint256 liquidatedCollateralAmount,\n address liquidator,\n bool receiveAToken\n );\n\n /**\n * @dev Emitted when the state of a reserve is updated.\n * @param reserve The address of the underlying asset of the reserve\n * @param liquidityRate The next liquidity rate\n * @param stableBorrowRate The next stable borrow rate\n * @param variableBorrowRate The next variable borrow rate\n * @param liquidityIndex The next liquidity index\n * @param variableBorrowIndex The next variable borrow index\n */\n event ReserveDataUpdated(\n address indexed reserve,\n uint256 liquidityRate,\n uint256 stableBorrowRate,\n uint256 variableBorrowRate,\n uint256 liquidityIndex,\n uint256 variableBorrowIndex\n );\n\n /**\n * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.\n * @param reserve The address of the reserve\n * @param amountMinted The amount minted to the treasury\n */\n event MintedToTreasury(address indexed reserve, uint256 amountMinted);\n\n /**\n * @notice Mints an `amount` of aTokens to the `onBehalfOf`\n * @param asset The address of the underlying asset to mint\n * @param amount The amount to mint\n * @param onBehalfOf The address that will receive the aTokens\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function mintUnbacked(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @notice Back the current unbacked underlying with `amount` and pay `fee`.\n * @param asset The address of the underlying asset to back\n * @param amount The amount to back\n * @param fee The amount paid in fees\n * @return The backed amount\n */\n function backUnbacked(address asset, uint256 amount, uint256 fee)\n external\n returns (uint256);\n\n /**\n * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User supplies 100 USDC and gets in return 100 aUSDC\n * @param asset The address of the underlying asset to supply\n * @param amount The amount to be supplied\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function supply(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n\n /**\n * @notice Supply with transfer approval of asset to be supplied done via permit function\n * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713\n * @param asset The address of the underlying asset to supply\n * @param amount The amount to be supplied\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param deadline The deadline timestamp that the permit is valid\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n * @param permitV The V parameter of ERC712 permit sig\n * @param permitR The R parameter of ERC712 permit sig\n * @param permitS The S parameter of ERC712 permit sig\n */\n function supplyWithPermit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode,\n uint256 deadline,\n uint8 permitV,\n bytes32 permitR,\n bytes32 permitS\n ) external;\n\n /**\n * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned\n * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC\n * @param asset The address of the underlying asset to withdraw\n * @param amount The underlying amount to be withdrawn\n * - Send the value type(uint256).max in order to withdraw the whole aToken balance\n * @param to The address that will receive the underlying, same as msg.sender if the user\n * wants to receive it on his own wallet, or a different address if the beneficiary is a\n * different wallet\n * @return The final amount withdrawn\n */\n function withdraw(address asset, uint256 amount, address to)\n external\n returns (uint256);\n\n /**\n * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower\n * already supplied enough collateral, or he was given enough allowance by a credit delegator on the\n * corresponding debt token (StableDebtToken or VariableDebtToken)\n * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet\n * and 100 stable/variable debt tokens, depending on the `interestRateMode`\n * @param asset The address of the underlying asset to borrow\n * @param amount The amount to be borrowed\n * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable\n * @param referralCode The code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself\n * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator\n * if he has been given credit delegation allowance\n */\n function borrow(\n address asset,\n uint256 amount,\n uint256 interestRateMode,\n uint16 referralCode,\n address onBehalfOf\n ) external;\n\n /**\n * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned\n * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address\n * @param asset The address of the borrowed underlying asset previously borrowed\n * @param amount The amount to repay\n * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\n * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\n * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the\n * user calling the function if he wants to reduce/remove his own debt, or the address of any other\n * other borrower whose debt should be removed\n * @return The final amount repaid\n */\n function repay(\n address asset,\n uint256 amount,\n uint256 interestRateMode,\n address onBehalfOf\n ) external returns (uint256);\n\n /**\n * @notice Repay with transfer approval of asset to be repaid done via permit function\n * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713\n * @param asset The address of the borrowed underlying asset previously borrowed\n * @param amount The amount to repay\n * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\n * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\n * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the\n * user calling the function if he wants to reduce/remove his own debt, or the address of any other\n * other borrower whose debt should be removed\n * @param deadline The deadline timestamp that the permit is valid\n * @param permitV The V parameter of ERC712 permit sig\n * @param permitR The R parameter of ERC712 permit sig\n * @param permitS The S parameter of ERC712 permit sig\n * @return The final amount repaid\n */\n function repayWithPermit(\n address asset,\n uint256 amount,\n uint256 interestRateMode,\n address onBehalfOf,\n uint256 deadline,\n uint8 permitV,\n bytes32 permitR,\n bytes32 permitS\n ) external returns (uint256);\n\n /**\n * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the\n * equivalent debt tokens\n * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens\n * @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken\n * balance is not enough to cover the whole debt\n * @param asset The address of the borrowed underlying asset previously borrowed\n * @param amount The amount to repay\n * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`\n * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable\n * @return The final amount repaid\n */\n function repayWithATokens(\n address asset,\n uint256 amount,\n uint256 interestRateMode\n ) external returns (uint256);\n\n /**\n * @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa\n * @param asset The address of the underlying asset borrowed\n * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable\n */\n function swapBorrowRateMode(address asset, uint256 interestRateMode)\n external;\n\n /**\n * @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.\n * - Users can be rebalanced if the following conditions are satisfied:\n * 1. Usage ratio is above 95%\n * 2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too\n * much has been borrowed at a stable rate and suppliers are not earning enough\n * @param asset The address of the underlying asset borrowed\n * @param user The address of the user to be rebalanced\n */\n function rebalanceStableBorrowRate(address asset, address user) external;\n\n /**\n * @notice Allows suppliers to enable/disable a specific supplied asset as collateral\n * @param asset The address of the underlying asset supplied\n * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise\n */\n function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)\n external;\n\n /**\n * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1\n * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives\n * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk\n * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation\n * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation\n * @param user The address of the borrower getting liquidated\n * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover\n * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants\n * to receive the underlying collateral asset directly\n */\n function liquidationCall(\n address collateralAsset,\n address debtAsset,\n address user,\n uint256 debtToCover,\n bool receiveAToken\n ) external;\n\n /**\n * @notice Allows smartcontracts to access the liquidity of the pool within one transaction,\n * as long as the amount taken plus a fee is returned.\n * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept\n * into consideration. For further details please visit https://docs.aave.com/developers/\n * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface\n * @param assets The addresses of the assets being flash-borrowed\n * @param amounts The amounts of the assets being flash-borrowed\n * @param interestRateModes Types of the debt to open if the flash loan is not returned:\n * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver\n * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\n * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address\n * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2\n * @param params Variadic packed params to pass to the receiver as extra information\n * @param referralCode The code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function flashLoan(\n address receiverAddress,\n address[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata interestRateModes,\n address onBehalfOf,\n bytes calldata params,\n uint16 referralCode\n ) external;\n\n /**\n * @notice Allows smartcontracts to access the liquidity of the pool within one transaction,\n * as long as the amount taken plus a fee is returned.\n * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept\n * into consideration. For further details please visit https://docs.aave.com/developers/\n * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface\n * @param asset The address of the asset being flash-borrowed\n * @param amount The amount of the asset being flash-borrowed\n * @param params Variadic packed params to pass to the receiver as extra information\n * @param referralCode The code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function flashLoanSimple(\n address receiverAddress,\n address asset,\n uint256 amount,\n bytes calldata params,\n uint16 referralCode\n ) external;\n\n /**\n * @notice Returns the user account data across all the reserves\n * @param user The address of the user\n * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed\n * @return totalDebtBase The total debt of the user in the base currency used by the price feed\n * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed\n * @return currentLiquidationThreshold The liquidation threshold of the user\n * @return ltv The loan to value of The user\n * @return healthFactor The current health factor of the user\n */\n function getUserAccountData(address user)\n external\n view\n returns (\n uint256 totalCollateralBase,\n uint256 totalDebtBase,\n uint256 availableBorrowsBase,\n uint256 currentLiquidationThreshold,\n uint256 ltv,\n uint256 healthFactor\n );\n\n /**\n * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an\n * interest rate strategy\n * @dev Only callable by the PoolConfigurator contract\n * @param asset The address of the underlying asset of the reserve\n * @param aTokenAddress The address of the aToken that will be assigned to the reserve\n * @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve\n * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve\n * @param interestRateStrategyAddress The address of the interest rate strategy contract\n */\n function initReserve(\n address asset,\n address aTokenAddress,\n address stableDebtAddress,\n address variableDebtAddress,\n address interestRateStrategyAddress\n ) external;\n\n /**\n * @notice Drop a reserve\n * @dev Only callable by the PoolConfigurator contract\n * @param asset The address of the underlying asset of the reserve\n */\n function dropReserve(address asset) external;\n\n /**\n * @notice Updates the address of the interest rate strategy contract\n * @dev Only callable by the PoolConfigurator contract\n * @param asset The address of the underlying asset of the reserve\n * @param rateStrategyAddress The address of the interest rate strategy contract\n */\n function setReserveInterestRateStrategyAddress(\n address asset,\n address rateStrategyAddress\n ) external;\n\n /**\n * @notice Sets the configuration bitmap of the reserve as a whole\n * @dev Only callable by the PoolConfigurator contract\n * @param asset The address of the underlying asset of the reserve\n * @param configuration The new configuration bitmap\n */\n function setConfiguration(\n address asset,\n DataTypes.ReserveConfigurationMap calldata configuration\n ) external;\n\n /**\n * @notice Returns the configuration of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The configuration of the reserve\n */\n function getConfiguration(address asset)\n external\n view\n returns (DataTypes.ReserveConfigurationMap memory);\n\n /**\n * @notice Returns the configuration of the user across all the reserves\n * @param user The user address\n * @return The configuration of the user\n */\n function getUserConfiguration(address user)\n external\n view\n returns (DataTypes.UserConfigurationMap memory);\n\n /**\n * @notice Returns the normalized income of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The reserve's normalized income\n */\n function getReserveNormalizedIncome(address asset)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the normalized variable debt per unit of asset\n * @dev WARNING: This function is intended to be used primarily by the protocol itself to get a\n * \"dynamic\" variable index based on time, current stored index and virtual rate at the current\n * moment (approx. a borrower would get if opening a position). This means that is always used in\n * combination with variable debt supply/balances.\n * If using this function externally, consider that is possible to have an increasing normalized\n * variable debt that is not equivalent to how the variable debt index would be updated in storage\n * (e.g. only updates with non-zero variable debt supply)\n * @param asset The address of the underlying asset of the reserve\n * @return The reserve normalized variable debt\n */\n function getReserveNormalizedVariableDebt(address asset)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the state and configuration of the reserve\n * @param asset The address of the underlying asset of the reserve\n * @return The state and configuration data of the reserve\n */\n function getReserveData(address asset)\n external\n view\n returns (DataTypes.ReserveData memory);\n\n /**\n * @notice Validates and finalizes an aToken transfer\n * @dev Only callable by the overlying aToken of the `asset`\n * @param asset The address of the underlying asset of the aToken\n * @param from The user from which the aTokens are transferred\n * @param to The user receiving the aTokens\n * @param amount The amount being transferred/withdrawn\n * @param balanceFromBefore The aToken balance of the `from` user before the transfer\n * @param balanceToBefore The aToken balance of the `to` user before the transfer\n */\n function finalizeTransfer(\n address asset,\n address from,\n address to,\n uint256 amount,\n uint256 balanceFromBefore,\n uint256 balanceToBefore\n ) external;\n\n /**\n * @notice Returns the list of the underlying assets of all the initialized reserves\n * @dev It does not include dropped reserves\n * @return The addresses of the underlying assets of the initialized reserves\n */\n function getReservesList() external view returns (address[] memory);\n\n /**\n * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct\n * @param id The id of the reserve as stored in the DataTypes.ReserveData struct\n * @return The address of the reserve associated with id\n */\n function getReserveAddressById(uint16 id) external view returns (address);\n\n /**\n * @notice Returns the PoolAddressesProvider connected to this contract\n * @return The address of the PoolAddressesProvider\n */\n function ADDRESSES_PROVIDER()\n external\n view\n returns (IPoolAddressesProvider);\n\n /**\n * @notice Updates the protocol fee on the bridging\n * @param bridgeProtocolFee The part of the premium sent to the protocol treasury\n */\n function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external;\n\n /**\n * @notice Updates flash loan premiums. Flash loan premium consists of two parts:\n * - A part is sent to aToken holders as extra, one time accumulated interest\n * - A part is collected by the protocol treasury\n * @dev The total premium is calculated on the total borrowed amount\n * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal`\n * @dev Only callable by the PoolConfigurator contract\n * @param flashLoanPremiumTotal The total premium, expressed in bps\n * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps\n */\n function updateFlashloanPremiums(\n uint128 flashLoanPremiumTotal,\n uint128 flashLoanPremiumToProtocol\n ) external;\n\n /**\n * @notice Configures a new category for the eMode.\n * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.\n * The category 0 is reserved as it's the default for volatile assets\n * @param id The id of the category\n * @param config The configuration of the category\n */\n function configureEModeCategory(\n uint8 id,\n DataTypes.EModeCategory memory config\n ) external;\n\n /**\n * @notice Returns the data of an eMode category\n * @param id The id of the category\n * @return The configuration data of the category\n */\n function getEModeCategoryData(uint8 id)\n external\n view\n returns (DataTypes.EModeCategory memory);\n\n /**\n * @notice Allows a user to use the protocol in eMode\n * @param categoryId The id of the category\n */\n function setUserEMode(uint8 categoryId) external;\n\n /**\n * @notice Returns the eMode the user is using\n * @param user The address of the user\n * @return The eMode id\n */\n function getUserEMode(address user) external view returns (uint256);\n\n /**\n * @notice Resets the isolation mode total debt of the given asset to zero\n * @dev It requires the given asset has zero debt ceiling\n * @param asset The address of the underlying asset to reset the isolationModeTotalDebt\n */\n function resetIsolationModeTotalDebt(address asset) external;\n\n /**\n * @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate\n * @return The percentage of available liquidity to borrow, expressed in bps\n */\n function MAX_STABLE_RATE_BORROW_SIZE_PERCENT()\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the total fee on flash loans\n * @return The total fee on flashloans\n */\n function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);\n\n /**\n * @notice Returns the part of the bridge fees sent to protocol\n * @return The bridge fee sent to the protocol treasury\n */\n function BRIDGE_PROTOCOL_FEE() external view returns (uint256);\n\n /**\n * @notice Returns the part of the flashloan fees sent to protocol\n * @return The flashloan fee sent to the protocol treasury\n */\n function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128);\n\n /**\n * @notice Returns the maximum number of reserves supported to be listed in this Pool\n * @return The maximum number of reserves supported\n */\n function MAX_NUMBER_RESERVES() external view returns (uint16);\n\n /**\n * @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens\n * @param assets The list of reserves for which the minting needs to be executed\n */\n function mintToTreasury(address[] calldata assets) external;\n\n /**\n * @notice Rescue and transfer tokens locked in this contract\n * @param token The address of the token\n * @param to The address of the recipient\n * @param amount The amount of token to transfer\n */\n function rescueTokens(address token, address to, uint256 amount) external;\n\n /**\n * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.\n * - E.g. User supplies 100 USDC and gets in return 100 aUSDC\n * @dev Deprecated: Use the `supply` function instead\n * @param asset The address of the underlying asset to supply\n * @param amount The amount to be supplied\n * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user\n * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens\n * is a different wallet\n * @param referralCode Code used to register the integrator originating the operation, for potential rewards.\n * 0 if the action is executed directly by the user, without any middle-man\n */\n function deposit(\n address asset,\n uint256 amount,\n address onBehalfOf,\n uint16 referralCode\n ) external;\n}\n" + }, + "contracts/interfaces/aave/IPoolAddressesProvider.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\npragma solidity ^0.8.0;\n\n/**\n * @title IPoolAddressesProvider\n * @author Aave\n * @notice Defines the basic interface for a Pool Addresses Provider.\n */\ninterface IPoolAddressesProvider {\n /**\n * @dev Emitted when the market identifier is updated.\n * @param oldMarketId The old id of the market\n * @param newMarketId The new id of the market\n */\n event MarketIdSet(string indexed oldMarketId, string indexed newMarketId);\n\n /**\n * @dev Emitted when the pool is updated.\n * @param oldAddress The old address of the Pool\n * @param newAddress The new address of the Pool\n */\n event PoolUpdated(address indexed oldAddress, address indexed newAddress);\n\n /**\n * @dev Emitted when the pool configurator is updated.\n * @param oldAddress The old address of the PoolConfigurator\n * @param newAddress The new address of the PoolConfigurator\n */\n event PoolConfiguratorUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the price oracle is updated.\n * @param oldAddress The old address of the PriceOracle\n * @param newAddress The new address of the PriceOracle\n */\n event PriceOracleUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the ACL manager is updated.\n * @param oldAddress The old address of the ACLManager\n * @param newAddress The new address of the ACLManager\n */\n event ACLManagerUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the ACL admin is updated.\n * @param oldAddress The old address of the ACLAdmin\n * @param newAddress The new address of the ACLAdmin\n */\n event ACLAdminUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the price oracle sentinel is updated.\n * @param oldAddress The old address of the PriceOracleSentinel\n * @param newAddress The new address of the PriceOracleSentinel\n */\n event PriceOracleSentinelUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the pool data provider is updated.\n * @param oldAddress The old address of the PoolDataProvider\n * @param newAddress The new address of the PoolDataProvider\n */\n event PoolDataProviderUpdated(\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when a new proxy is created.\n * @param id The identifier of the proxy\n * @param proxyAddress The address of the created proxy contract\n * @param implementationAddress The address of the implementation contract\n */\n event ProxyCreated(\n bytes32 indexed id,\n address indexed proxyAddress,\n address indexed implementationAddress\n );\n\n /**\n * @dev Emitted when a new non-proxied contract address is registered.\n * @param id The identifier of the contract\n * @param oldAddress The address of the old contract\n * @param newAddress The address of the new contract\n */\n event AddressSet(\n bytes32 indexed id,\n address indexed oldAddress,\n address indexed newAddress\n );\n\n /**\n * @dev Emitted when the implementation of the proxy registered with id is updated\n * @param id The identifier of the contract\n * @param proxyAddress The address of the proxy contract\n * @param oldImplementationAddress The address of the old implementation contract\n * @param newImplementationAddress The address of the new implementation contract\n */\n event AddressSetAsProxy(\n bytes32 indexed id,\n address indexed proxyAddress,\n address oldImplementationAddress,\n address indexed newImplementationAddress\n );\n\n /**\n * @notice Returns the id of the Aave market to which this contract points to.\n * @return The market id\n */\n function getMarketId() external view returns (string memory);\n\n /**\n * @notice Associates an id with a specific PoolAddressesProvider.\n * @dev This can be used to create an onchain registry of PoolAddressesProviders to\n * identify and validate multiple Aave markets.\n * @param newMarketId The market id\n */\n function setMarketId(string calldata newMarketId) external;\n\n /**\n * @notice Returns an address by its identifier.\n * @dev The returned address might be an EOA or a contract, potentially proxied\n * @dev It returns ZERO if there is no registered address with the given id\n * @param id The id\n * @return The address of the registered for the specified id\n */\n function getAddress(bytes32 id) external view returns (address);\n\n /**\n * @notice General function to update the implementation of a proxy registered with\n * certain `id`. If there is no proxy registered, it will instantiate one and\n * set as implementation the `newImplementationAddress`.\n * @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit\n * setter function, in order to avoid unexpected consequences\n * @param id The id\n * @param newImplementationAddress The address of the new implementation\n */\n function setAddressAsProxy(bytes32 id, address newImplementationAddress)\n external;\n\n /**\n * @notice Sets an address for an id replacing the address saved in the addresses map.\n * @dev IMPORTANT Use this function carefully, as it will do a hard replacement\n * @param id The id\n * @param newAddress The address to set\n */\n function setAddress(bytes32 id, address newAddress) external;\n\n /**\n * @notice Returns the address of the Pool proxy.\n * @return The Pool proxy address\n */\n function getPool() external view returns (address);\n\n /**\n * @notice Updates the implementation of the Pool, or creates a proxy\n * setting the new `pool` implementation when the function is called for the first time.\n * @param newPoolImpl The new Pool implementation\n */\n function setPoolImpl(address newPoolImpl) external;\n\n /**\n * @notice Returns the address of the PoolConfigurator proxy.\n * @return The PoolConfigurator proxy address\n */\n function getPoolConfigurator() external view returns (address);\n\n /**\n * @notice Updates the implementation of the PoolConfigurator, or creates a proxy\n * setting the new `PoolConfigurator` implementation when the function is called for the first time.\n * @param newPoolConfiguratorImpl The new PoolConfigurator implementation\n */\n function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external;\n\n /**\n * @notice Returns the address of the price oracle.\n * @return The address of the PriceOracle\n */\n function getPriceOracle() external view returns (address);\n\n /**\n * @notice Updates the address of the price oracle.\n * @param newPriceOracle The address of the new PriceOracle\n */\n function setPriceOracle(address newPriceOracle) external;\n\n /**\n * @notice Returns the address of the ACL manager.\n * @return The address of the ACLManager\n */\n function getACLManager() external view returns (address);\n\n /**\n * @notice Updates the address of the ACL manager.\n * @param newAclManager The address of the new ACLManager\n */\n function setACLManager(address newAclManager) external;\n\n /**\n * @notice Returns the address of the ACL admin.\n * @return The address of the ACL admin\n */\n function getACLAdmin() external view returns (address);\n\n /**\n * @notice Updates the address of the ACL admin.\n * @param newAclAdmin The address of the new ACL admin\n */\n function setACLAdmin(address newAclAdmin) external;\n\n /**\n * @notice Returns the address of the price oracle sentinel.\n * @return The address of the PriceOracleSentinel\n */\n function getPriceOracleSentinel() external view returns (address);\n\n /**\n * @notice Updates the address of the price oracle sentinel.\n * @param newPriceOracleSentinel The address of the new PriceOracleSentinel\n */\n function setPriceOracleSentinel(address newPriceOracleSentinel) external;\n\n /**\n * @notice Returns the address of the data provider.\n * @return The address of the DataProvider\n */\n function getPoolDataProvider() external view returns (address);\n\n /**\n * @notice Updates the address of the data provider.\n * @param newDataProvider The address of the new DataProvider\n */\n function setPoolDataProvider(address newDataProvider) external;\n}\n" + }, + "contracts/interfaces/escrow/ICollateralEscrowV1.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nenum CollateralType {\n ERC20,\n ERC721,\n ERC1155\n}\n\nstruct Collateral {\n CollateralType _collateralType;\n uint256 _amount;\n uint256 _tokenId;\n address _collateralAddress;\n}\n\ninterface ICollateralEscrowV1 {\n /**\n * @notice Deposits a collateral asset into the escrow.\n * @param _collateralType The type of collateral asset to deposit (ERC721, ERC1155).\n * @param _collateralAddress The address of the collateral token.i feel\n * @param _amount The amount to deposit.\n */\n function depositAsset(\n CollateralType _collateralType,\n address _collateralAddress,\n uint256 _amount,\n uint256 _tokenId\n ) external payable;\n\n /**\n * @notice Withdraws a collateral asset from the escrow.\n * @param _collateralAddress The address of the collateral contract.\n * @param _amount The amount to withdraw.\n * @param _recipient The address to send the assets to.\n */\n function withdraw(\n address _collateralAddress,\n uint256 _amount,\n address _recipient\n ) external;\n\n function withdrawDustTokens( \n address _tokenAddress, \n uint256 _amount,\n address _recipient\n ) external;\n\n\n function getBid() external view returns (uint256);\n\n function initialize(uint256 _bidId) external;\n\n\n}\n" + }, + "contracts/interfaces/IASRegistry.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./IASResolver.sol\";\n\n/**\n * @title The global AS registry interface.\n */\ninterface IASRegistry {\n /**\n * @title A struct representing a record for a submitted AS (Attestation Schema).\n */\n struct ASRecord {\n // A unique identifier of the AS.\n bytes32 uuid;\n // Optional schema resolver.\n IASResolver resolver;\n // Auto-incrementing index for reference, assigned by the registry itself.\n uint256 index;\n // Custom specification of the AS (e.g., an ABI).\n bytes schema;\n }\n\n /**\n * @dev Triggered when a new AS has been registered\n *\n * @param uuid The AS UUID.\n * @param index The AS index.\n * @param schema The AS schema.\n * @param resolver An optional AS schema resolver.\n * @param attester The address of the account used to register the AS.\n */\n event Registered(\n bytes32 indexed uuid,\n uint256 indexed index,\n bytes schema,\n IASResolver resolver,\n address attester\n );\n\n /**\n * @dev Submits and reserve a new AS\n *\n * @param schema The AS data schema.\n * @param resolver An optional AS schema resolver.\n *\n * @return The UUID of the new AS.\n */\n function register(bytes calldata schema, IASResolver resolver)\n external\n returns (bytes32);\n\n /**\n * @dev Returns an existing AS by UUID\n *\n * @param uuid The UUID of the AS to retrieve.\n *\n * @return The AS data members.\n */\n function getAS(bytes32 uuid) external view returns (ASRecord memory);\n\n /**\n * @dev Returns the global counter for the total number of attestations\n *\n * @return The global counter for the total number of attestations.\n */\n function getASCount() external view returns (uint256);\n}\n" + }, + "contracts/interfaces/IASResolver.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n\n// SPDX-License-Identifier: MIT\n\n/**\n * @title The interface of an optional AS resolver.\n */\ninterface IASResolver {\n /**\n * @dev Returns whether the resolver supports ETH transfers\n */\n function isPayable() external pure returns (bool);\n\n /**\n * @dev Resolves an attestation and verifier whether its data conforms to the spec.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The AS data schema.\n * @param data The actual attestation data.\n * @param expirationTime The expiration time of the attestation.\n * @param msgSender The sender of the original attestation message.\n *\n * @return Whether the data is valid according to the scheme.\n */\n function resolve(\n address recipient,\n bytes calldata schema,\n bytes calldata data,\n uint256 expirationTime,\n address msgSender\n ) external payable returns (bool);\n}\n" + }, + "contracts/interfaces/ICollateralManager.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nimport { Collateral } from \"./escrow/ICollateralEscrowV1.sol\";\n\ninterface ICollateralManager {\n /**\n * @notice Checks the validity of a borrower's collateral balance.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral asset.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function commitCollateral(\n uint256 _bidId,\n Collateral[] calldata _collateralInfo\n ) external returns (bool validation_);\n\n /**\n * @notice Checks the validity of a borrower's collateral balance and commits it to a bid.\n * @param _bidId The id of the associated bid.\n * @param _collateralInfo Additional information about the collateral asset.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function commitCollateral(\n uint256 _bidId,\n Collateral calldata _collateralInfo\n ) external returns (bool validation_);\n\n function checkBalances(\n address _borrowerAddress,\n Collateral[] calldata _collateralInfo\n ) external returns (bool validated_, bool[] memory checks_);\n\n /**\n * @notice Deploys a new collateral escrow.\n * @param _bidId The associated bidId of the collateral escrow.\n */\n function deployAndDeposit(uint256 _bidId) external;\n\n /**\n * @notice Gets the address of a deployed escrow.\n * @notice _bidId The bidId to return the escrow for.\n * @return The address of the escrow.\n */\n function getEscrow(uint256 _bidId) external view returns (address);\n\n /**\n * @notice Gets the collateral info for a given bid id.\n * @param _bidId The bidId to return the collateral info for.\n * @return The stored collateral info.\n */\n function getCollateralInfo(uint256 _bidId)\n external\n view\n returns (Collateral[] memory);\n\n function getCollateralAmount(uint256 _bidId, address collateralAssetAddress)\n external\n view\n returns (uint256 _amount);\n\n /**\n * @notice Withdraws deposited collateral from the created escrow of a bid.\n * @param _bidId The id of the bid to withdraw collateral for.\n */\n function withdraw(uint256 _bidId) external;\n\n /**\n * @notice Re-checks the validity of a borrower's collateral balance committed to a bid.\n * @param _bidId The id of the associated bid.\n * @return validation_ Boolean indicating if the collateral balance was validated.\n */\n function revalidateCollateral(uint256 _bidId) external returns (bool);\n\n /**\n * @notice Sends the deposited collateral to a lender of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n */\n function lenderClaimCollateral(uint256 _bidId) external;\n\n\n\n /**\n * @notice Sends the deposited collateral to a lender of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n * @param _collateralRecipient the address that will receive the collateral \n */\n function lenderClaimCollateralWithRecipient(uint256 _bidId, address _collateralRecipient) external;\n\n\n /**\n * @notice Sends the deposited collateral to a liquidator of a bid.\n * @notice Can only be called by the protocol.\n * @param _bidId The id of the liquidated bid.\n * @param _liquidatorAddress The address of the liquidator to send the collateral to.\n */\n function liquidateCollateral(uint256 _bidId, address _liquidatorAddress)\n external;\n}\n" + }, + "contracts/interfaces/ICommitmentRolloverLoan.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ICommitmentRolloverLoan {\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n }\n}\n" + }, + "contracts/interfaces/IEAS.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./IASRegistry.sol\";\nimport \"./IEASEIP712Verifier.sol\";\n\n/**\n * @title EAS - Ethereum Attestation Service interface\n */\ninterface IEAS {\n /**\n * @dev A struct representing a single attestation.\n */\n struct Attestation {\n // A unique identifier of the attestation.\n bytes32 uuid;\n // A unique identifier of the AS.\n bytes32 schema;\n // The recipient of the attestation.\n address recipient;\n // The attester/sender of the attestation.\n address attester;\n // The time when the attestation was created (Unix timestamp).\n uint256 time;\n // The time when the attestation expires (Unix timestamp).\n uint256 expirationTime;\n // The time when the attestation was revoked (Unix timestamp).\n uint256 revocationTime;\n // The UUID of the related attestation.\n bytes32 refUUID;\n // Custom attestation data.\n bytes data;\n }\n\n /**\n * @dev Triggered when an attestation has been made.\n *\n * @param recipient The recipient of the attestation.\n * @param attester The attesting account.\n * @param uuid The UUID the revoked attestation.\n * @param schema The UUID of the AS.\n */\n event Attested(\n address indexed recipient,\n address indexed attester,\n bytes32 uuid,\n bytes32 indexed schema\n );\n\n /**\n * @dev Triggered when an attestation has been revoked.\n *\n * @param recipient The recipient of the attestation.\n * @param attester The attesting account.\n * @param schema The UUID of the AS.\n * @param uuid The UUID the revoked attestation.\n */\n event Revoked(\n address indexed recipient,\n address indexed attester,\n bytes32 uuid,\n bytes32 indexed schema\n );\n\n /**\n * @dev Returns the address of the AS global registry.\n *\n * @return The address of the AS global registry.\n */\n function getASRegistry() external view returns (IASRegistry);\n\n /**\n * @dev Returns the address of the EIP712 verifier used to verify signed attestations.\n *\n * @return The address of the EIP712 verifier used to verify signed attestations.\n */\n function getEIP712Verifier() external view returns (IEASEIP712Verifier);\n\n /**\n * @dev Returns the global counter for the total number of attestations.\n *\n * @return The global counter for the total number of attestations.\n */\n function getAttestationsCount() external view returns (uint256);\n\n /**\n * @dev Attests to a specific AS.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param expirationTime The expiration time of the attestation.\n * @param refUUID An optional related attestation's UUID.\n * @param data Additional custom data.\n *\n * @return The UUID of the new attestation.\n */\n function attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data\n ) external payable returns (bytes32);\n\n /**\n * @dev Attests to a specific AS using a provided EIP712 signature.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param expirationTime The expiration time of the attestation.\n * @param refUUID An optional related attestation's UUID.\n * @param data Additional custom data.\n * @param attester The attesting account.\n * @param v The recovery ID.\n * @param r The x-coordinate of the nonce R.\n * @param s The signature data.\n *\n * @return The UUID of the new attestation.\n */\n function attestByDelegation(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external payable returns (bytes32);\n\n /**\n * @dev Revokes an existing attestation to a specific AS.\n *\n * @param uuid The UUID of the attestation to revoke.\n */\n function revoke(bytes32 uuid) external;\n\n /**\n * @dev Attests to a specific AS using a provided EIP712 signature.\n *\n * @param uuid The UUID of the attestation to revoke.\n * @param attester The attesting account.\n * @param v The recovery ID.\n * @param r The x-coordinate of the nonce R.\n * @param s The signature data.\n */\n function revokeByDelegation(\n bytes32 uuid,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns an existing attestation by UUID.\n *\n * @param uuid The UUID of the attestation to retrieve.\n *\n * @return The attestation data members.\n */\n function getAttestation(bytes32 uuid)\n external\n view\n returns (Attestation memory);\n\n /**\n * @dev Checks whether an attestation exists.\n *\n * @param uuid The UUID of the attestation to retrieve.\n *\n * @return Whether an attestation exists.\n */\n function isAttestationValid(bytes32 uuid) external view returns (bool);\n\n /**\n * @dev Checks whether an attestation is active.\n *\n * @param uuid The UUID of the attestation to retrieve.\n *\n * @return Whether an attestation is active.\n */\n function isAttestationActive(bytes32 uuid) external view returns (bool);\n\n /**\n * @dev Returns all received attestation UUIDs.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function getReceivedAttestationUUIDs(\n address recipient,\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view returns (bytes32[] memory);\n\n /**\n * @dev Returns the number of received attestation UUIDs.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n *\n * @return The number of attestations.\n */\n function getReceivedAttestationUUIDsCount(address recipient, bytes32 schema)\n external\n view\n returns (uint256);\n\n /**\n * @dev Returns all sent attestation UUIDs.\n *\n * @param attester The attesting account.\n * @param schema The UUID of the AS.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function getSentAttestationUUIDs(\n address attester,\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view returns (bytes32[] memory);\n\n /**\n * @dev Returns the number of sent attestation UUIDs.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n *\n * @return The number of attestations.\n */\n function getSentAttestationUUIDsCount(address recipient, bytes32 schema)\n external\n view\n returns (uint256);\n\n /**\n * @dev Returns all attestations related to a specific attestation.\n *\n * @param uuid The UUID of the attestation to retrieve.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function getRelatedAttestationUUIDs(\n bytes32 uuid,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view returns (bytes32[] memory);\n\n /**\n * @dev Returns the number of related attestation UUIDs.\n *\n * @param uuid The UUID of the attestation to retrieve.\n *\n * @return The number of related attestations.\n */\n function getRelatedAttestationUUIDsCount(bytes32 uuid)\n external\n view\n returns (uint256);\n\n /**\n * @dev Returns all per-schema attestation UUIDs.\n *\n * @param schema The UUID of the AS.\n * @param start The offset to start from.\n * @param length The number of total members to retrieve.\n * @param reverseOrder Whether the offset starts from the end and the data is returned in reverse.\n *\n * @return An array of attestation UUIDs.\n */\n function getSchemaAttestationUUIDs(\n bytes32 schema,\n uint256 start,\n uint256 length,\n bool reverseOrder\n ) external view returns (bytes32[] memory);\n\n /**\n * @dev Returns the number of per-schema attestation UUIDs.\n *\n * @param schema The UUID of the AS.\n *\n * @return The number of attestations.\n */\n function getSchemaAttestationUUIDsCount(bytes32 schema)\n external\n view\n returns (uint256);\n}\n" + }, + "contracts/interfaces/IEASEIP712Verifier.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n\n// SPDX-License-Identifier: MIT\n\n/**\n * @title EIP712 typed signatures verifier for EAS delegated attestations interface.\n */\ninterface IEASEIP712Verifier {\n /**\n * @dev Returns the current nonce per-account.\n *\n * @param account The requested accunt.\n *\n * @return The current nonce.\n */\n function getNonce(address account) external view returns (uint256);\n\n /**\n * @dev Verifies signed attestation.\n *\n * @param recipient The recipient of the attestation.\n * @param schema The UUID of the AS.\n * @param expirationTime The expiration time of the attestation.\n * @param refUUID An optional related attestation's UUID.\n * @param data Additional custom data.\n * @param attester The attesting account.\n * @param v The recovery ID.\n * @param r The x-coordinate of the nonce R.\n * @param s The signature data.\n */\n function attest(\n address recipient,\n bytes32 schema,\n uint256 expirationTime,\n bytes32 refUUID,\n bytes calldata data,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Verifies signed revocations.\n *\n * @param uuid The UUID of the attestation to revoke.\n * @param attester The attesting account.\n * @param v The recovery ID.\n * @param r The x-coordinate of the nonce R.\n * @param s The signature data.\n */\n function revoke(\n bytes32 uuid,\n address attester,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "contracts/interfaces/IEscrowVault.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface IEscrowVault {\n /**\n * @notice Deposit tokens on behalf of another account\n * @param account The address of the account\n * @param token The address of the token\n * @param amount The amount to increase the balance\n */\n function deposit(address account, address token, uint256 amount) external;\n\n function withdraw(address token, uint256 amount) external ;\n}\n" + }, + "contracts/interfaces/IExtensionsContext.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IExtensionsContext {\n function hasExtension(address extension, address account)\n external\n view\n returns (bool);\n\n function addExtension(address extension) external;\n\n function revokeExtension(address extension) external;\n}\n" + }, + "contracts/interfaces/IFlashRolloverLoan_G4.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IFlashRolloverLoan_G4 {\n struct RolloverCallbackArgs {\n address lenderCommitmentForwarder;\n uint256 loanId;\n address borrower;\n uint256 borrowerAmount;\n bytes acceptCommitmentArgs;\n }\n}\n" + }, + "contracts/interfaces/IFlashRolloverLoan_G6.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IFlashRolloverLoan_G6 {\n struct RolloverCallbackArgs {\n address lenderCommitmentForwarder;\n uint256 loanId;\n address borrower;\n uint256 borrowerAmount;\n address rewardRecipient;\n uint256 rewardAmount;\n bytes acceptCommitmentArgs;\n }\n}\n" + }, + "contracts/interfaces/IFlashRolloverLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IFlashRolloverLoan {\n struct RolloverCallbackArgs { \n uint256 loanId;\n address borrower;\n uint256 borrowerAmount;\n bytes acceptCommitmentArgs;\n }\n}\n" + }, + "contracts/interfaces/IHasProtocolPausingManager.sol": { + "content": "\n\n\n\n\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\n//records the unpause timestamp s\ninterface IHasProtocolPausingManager {\n \n \n function getProtocolPausingManager() external view returns (address); \n\n // function isPauser(address _address) external view returns (bool); \n\n\n}\n" + }, + "contracts/interfaces/ILenderCommitmentForwarder_U1.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ILenderCommitmentForwarder_U1 {\n enum CommitmentCollateralType {\n NONE, // no collateral required\n ERC20,\n ERC721,\n ERC1155,\n ERC721_ANY_ID,\n ERC1155_ANY_ID,\n ERC721_MERKLE_PROOF,\n ERC1155_MERKLE_PROOF\n }\n\n /**\n * @notice Details about a lender's capital commitment.\n * @param maxPrincipal Amount of tokens being committed by the lender. Max amount that can be loaned.\n * @param expiration Expiration time in seconds, when the commitment expires.\n * @param maxDuration Length of time, in seconds that the lender's capital can be lent out for.\n * @param minInterestRate Minimum Annual percentage to be applied for loans using the lender's capital.\n * @param collateralTokenAddress The address for the token contract that must be used to provide collateral for loans for this commitment.\n * @param maxPrincipalPerCollateralAmount The amount of principal that can be used for a loan per each unit of collateral, expanded additionally by principal decimals.\n * @param collateralTokenType The type of asset of the collateralTokenAddress (ERC20, ERC721, or ERC1155).\n * @param lender The address of the lender for this commitment.\n * @param marketId The market id for this commitment.\n * @param principalTokenAddress The address for the token contract that will be used to provide principal for loans of this commitment.\n */\n struct Commitment {\n uint256 maxPrincipal;\n uint32 expiration;\n uint32 maxDuration;\n uint16 minInterestRate;\n address collateralTokenAddress;\n uint256 collateralTokenId; //we use this for the MerkleRootHash for type ERC721_MERKLE_PROOF\n uint256 maxPrincipalPerCollateralAmount;\n CommitmentCollateralType collateralTokenType;\n address lender;\n uint256 marketId;\n address principalTokenAddress;\n }\n\n struct PoolRouteConfig {\n address pool;\n bool zeroForOne;\n uint32 twapInterval;\n uint256 token0Decimals;\n uint256 token1Decimals;\n }\n\n // mapping(uint256 => Commitment) public commitments;\n\n function getCommitmentMarketId(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function getCommitmentLender(uint256 _commitmentId)\n external\n view\n returns (address);\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function createCommitmentWithUniswap(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList,\n PoolRouteConfig[] calldata _poolRoutes,\n uint16 _poolOracleLtvRatio\n ) external returns (uint256);\n\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) external returns (uint256 bidId_);\n\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) external returns (uint256 bidId_);\n\n\n function getCommitmentPrincipalTokenAddress(uint256 _commitmentId)\n external\n view\n returns (address);\n\n function getCommitmentCollateralTokenAddress(uint256 _commitmentId)\n external\n view\n returns (address);\n\n\n}\n" + }, + "contracts/interfaces/ILenderCommitmentForwarder.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ILenderCommitmentForwarder {\n enum CommitmentCollateralType {\n NONE, // no collateral required\n ERC20,\n ERC721,\n ERC1155,\n ERC721_ANY_ID,\n ERC1155_ANY_ID,\n ERC721_MERKLE_PROOF,\n ERC1155_MERKLE_PROOF\n }\n\n /**\n * @notice Details about a lender's capital commitment.\n * @param maxPrincipal Amount of tokens being committed by the lender. Max amount that can be loaned.\n * @param expiration Expiration time in seconds, when the commitment expires.\n * @param maxDuration Length of time, in seconds that the lender's capital can be lent out for.\n * @param minInterestRate Minimum Annual percentage to be applied for loans using the lender's capital.\n * @param collateralTokenAddress The address for the token contract that must be used to provide collateral for loans for this commitment.\n * @param maxPrincipalPerCollateralAmount The amount of principal that can be used for a loan per each unit of collateral, expanded additionally by principal decimals.\n * @param collateralTokenType The type of asset of the collateralTokenAddress (ERC20, ERC721, or ERC1155).\n * @param lender The address of the lender for this commitment.\n * @param marketId The market id for this commitment.\n * @param principalTokenAddress The address for the token contract that will be used to provide principal for loans of this commitment.\n */\n struct Commitment {\n uint256 maxPrincipal;\n uint32 expiration;\n uint32 maxDuration;\n uint16 minInterestRate;\n address collateralTokenAddress;\n uint256 collateralTokenId; //we use this for the MerkleRootHash for type ERC721_MERKLE_PROOF\n uint256 maxPrincipalPerCollateralAmount;\n CommitmentCollateralType collateralTokenType;\n address lender;\n uint256 marketId;\n address principalTokenAddress;\n }\n\n // mapping(uint256 => Commitment) public commitments;\n\n function getCommitmentMarketId(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function getCommitmentLender(uint256 _commitmentId)\n external\n view\n returns (address);\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256);\n\n function createCommitment(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList\n ) external returns (uint256);\n\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) external returns (uint256 bidId_);\n \n\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) external returns (uint256 bidId_);\n}\n" + }, + "contracts/interfaces/ILenderCommitmentGroup.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\nimport {IUniswapPricingLibrary} from \"../interfaces/IUniswapPricingLibrary.sol\";\ninterface ILenderCommitmentGroup {\n\n\n\n struct CommitmentGroupConfig {\n address principalTokenAddress;\n address collateralTokenAddress;\n uint256 marketId;\n uint32 maxLoanDuration;\n uint16 interestRateLowerBound;\n uint16 interestRateUpperBound;\n uint16 liquidityThresholdPercent;\n uint16 collateralRatio; //essentially the overcollateralization ratio. 10000 is 1:1 baseline ?\n \n }\n\n\n function initialize(\n CommitmentGroupConfig calldata _commitmentGroupConfig,\n IUniswapPricingLibrary.PoolRouteConfig[] calldata _poolOracleRoutes \n )\n external\n returns (\n //uint256 _maxPrincipalPerCollateralAmount //use oracle instead\n\n //ILenderCommitmentForwarder.Commitment calldata _createCommitmentArgs\n\n address poolSharesToken\n );\n\n function addPrincipalToCommitmentGroup(\n uint256 _amount,\n address _sharesRecipient,\n uint256 _minAmountOut\n ) external returns (uint256 sharesAmount_);\n\n\n function getTokenDifferenceFromLiquidations() external view returns (int256);\n\n}\n" + }, + "contracts/interfaces/ILenderManager.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n\n// SPDX-License-Identifier: MIT\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\n\nabstract contract ILenderManager is IERC721Upgradeable {\n /**\n * @notice Registers a new active lender for a loan, minting the nft.\n * @param _bidId The id for the loan to set.\n * @param _newLender The address of the new active lender.\n */\n function registerLoan(uint256 _bidId, address _newLender) external virtual;\n}\n" + }, + "contracts/interfaces/ILoanRepaymentCallbacks.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\n//tellerv2 should support this\ninterface ILoanRepaymentCallbacks {\n function setRepaymentListenerForBid(uint256 _bidId, address _listener)\n external;\n\n function getRepaymentListenerForBid(uint256 _bidId)\n external\n view\n returns (address);\n}\n" + }, + "contracts/interfaces/ILoanRepaymentListener.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ILoanRepaymentListener {\n function repayLoanCallback(\n uint256 bidId,\n address repayer,\n uint256 principalAmount,\n uint256 interestAmount\n ) external;\n}\n" + }, + "contracts/interfaces/IMarketLiquidityRewards.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IMarketLiquidityRewards {\n struct RewardAllocation {\n address allocator;\n address rewardTokenAddress;\n uint256 rewardTokenAmount;\n uint256 marketId;\n //requirements for loan\n address requiredPrincipalTokenAddress; //0 for any\n address requiredCollateralTokenAddress; //0 for any -- could be an enumerable set?\n uint256 minimumCollateralPerPrincipalAmount;\n uint256 rewardPerLoanPrincipalAmount;\n uint32 bidStartTimeMin;\n uint32 bidStartTimeMax;\n AllocationStrategy allocationStrategy;\n }\n\n enum AllocationStrategy {\n BORROWER,\n LENDER\n }\n\n function allocateRewards(RewardAllocation calldata _allocation)\n external\n returns (uint256 allocationId_);\n\n function increaseAllocationAmount(\n uint256 _allocationId,\n uint256 _tokenAmount\n ) external;\n\n function deallocateRewards(uint256 _allocationId, uint256 _amount) external;\n\n function claimRewards(uint256 _allocationId, uint256 _bidId) external;\n\n function rewardClaimedForBid(uint256 _bidId, uint256 _allocationId)\n external\n view\n returns (bool);\n\n function getRewardTokenAmount(uint256 _allocationId)\n external\n view\n returns (uint256);\n\n function initialize() external;\n}\n" + }, + "contracts/interfaces/IMarketRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../EAS/TellerAS.sol\";\nimport { PaymentType, PaymentCycleType } from \"../libraries/V2Calculations.sol\";\n\ninterface IMarketRegistry {\n function initialize(TellerAS tellerAs) external;\n\n function isVerifiedLender(uint256 _marketId, address _lender)\n external\n view\n returns (bool, bytes32);\n\n function isMarketOpen(uint256 _marketId) external view returns (bool);\n\n function isMarketClosed(uint256 _marketId) external view returns (bool);\n\n function isVerifiedBorrower(uint256 _marketId, address _borrower)\n external\n view\n returns (bool, bytes32);\n\n function getMarketOwner(uint256 _marketId) external view returns (address);\n\n function getMarketFeeRecipient(uint256 _marketId)\n external\n view\n returns (address);\n\n function getMarketURI(uint256 _marketId)\n external\n view\n returns (string memory);\n\n function getPaymentCycle(uint256 _marketId)\n external\n view\n returns (uint32, PaymentCycleType);\n\n function getPaymentDefaultDuration(uint256 _marketId)\n external\n view\n returns (uint32);\n\n function getBidExpirationTime(uint256 _marketId)\n external\n view\n returns (uint32);\n\n function getMarketplaceFee(uint256 _marketId)\n external\n view\n returns (uint16);\n\n function getPaymentType(uint256 _marketId)\n external\n view\n returns (PaymentType);\n\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n PaymentType _paymentType,\n PaymentCycleType _paymentCycleType,\n string calldata _uri\n ) external returns (uint256 marketId_);\n\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n string calldata _uri\n ) external returns (uint256 marketId_);\n\n function closeMarket(uint256 _marketId) external;\n}\n" + }, + "contracts/interfaces/IPausableTimestamp.sol": { + "content": "\n\n\n\n\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\n//records the unpause timestamp s\ninterface IPausableTimestamp {\n \n \n function getLastUnpausedAt() \n external view \n returns (uint256) ;\n\n // function setLastUnpausedAt() internal;\n\n\n\n}\n" + }, + "contracts/interfaces/IProtocolFee.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IProtocolFee {\n function protocolFee() external view returns (uint16);\n}\n" + }, + "contracts/interfaces/IProtocolPausingManager.sol": { + "content": "\n\n\n\n\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n\n//records the unpause timestamp s\ninterface IProtocolPausingManager {\n \n function isPauser(address _address) external view returns (bool);\n function protocolPaused() external view returns (bool);\n function liquidationsPaused() external view returns (bool);\n \n \n\n}\n" + }, + "contracts/interfaces/IReputationManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nenum RepMark {\n Good,\n Delinquent,\n Default\n}\n\ninterface IReputationManager {\n function initialize(address protocolAddress) external;\n\n function getDelinquentLoanIds(address _account)\n external\n returns (uint256[] memory);\n\n function getDefaultedLoanIds(address _account)\n external\n returns (uint256[] memory);\n\n function getCurrentDelinquentLoanIds(address _account)\n external\n returns (uint256[] memory);\n\n function getCurrentDefaultLoanIds(address _account)\n external\n returns (uint256[] memory);\n\n function updateAccountReputation(address _account) external;\n\n function updateAccountReputation(address _account, uint256 _bidId)\n external\n returns (RepMark);\n}\n" + }, + "contracts/interfaces/ISmartCommitment.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nenum CommitmentCollateralType {\n NONE, // no collateral required\n ERC20,\n ERC721,\n ERC1155,\n ERC721_ANY_ID,\n ERC1155_ANY_ID,\n ERC721_MERKLE_PROOF,\n ERC1155_MERKLE_PROOF\n}\n\ninterface ISmartCommitment {\n function getPrincipalTokenAddress() external view returns (address);\n\n function getMarketId() external view returns (uint256);\n\n function getCollateralTokenAddress() external view returns (address);\n\n function getCollateralTokenType()\n external\n view\n returns (CommitmentCollateralType);\n\n function getCollateralTokenId() external view returns (uint256);\n\n function getMinInterestRate(uint256 _delta) external view returns (uint16);\n\n function getMaxLoanDuration() external view returns (uint32);\n\n function getPrincipalAmountAvailableToBorrow()\n external\n view\n returns (uint256);\n\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount\n \n )\n external\n view\n returns (uint256);\n\n \n function acceptFundsForAcceptBid(\n address _borrower,\n uint256 _bidId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n address _collateralTokenAddress,\n uint256 _collateralTokenId,\n uint32 _loanDuration,\n uint16 _interestRate\n ) external;\n}\n" + }, + "contracts/interfaces/ISmartCommitmentForwarder.sol": { + "content": "\n\npragma solidity >=0.8.0 <0.9.0;\n\ninterface ISmartCommitmentForwarder {\n \n function acceptSmartCommitmentWithRecipient(\n address _smartCommitmentAddress,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) external returns (uint256 bidId) ;\n\n\n function setLiquidationProtocolFeePercent(uint256 _percent) \n external;\n\n function getLiquidationProtocolFeePercent() \n external view returns (uint256) ;\n\n\n\n}" + }, + "contracts/interfaces/ITellerV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport { Payment, BidState } from \"../TellerV2Storage.sol\";\nimport { Collateral } from \"./escrow/ICollateralEscrowV1.sol\";\n\ninterface ITellerV2 {\n /**\n * @notice Function for a borrower to create a bid for a loan.\n * @param _lendingToken The lending token asset requested to be borrowed.\n * @param _marketplaceId The unique id of the marketplace for the bid.\n * @param _principal The principal amount of the loan bid.\n * @param _duration The recurrent length of time before which a payment is due.\n * @param _APR The proposed interest rate for the loan bid.\n * @param _metadataURI The URI for additional borrower loan information as part of loan bid.\n * @param _receiver The address where the loan amount will be sent to.\n */\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver\n ) external returns (uint256 bidId_);\n\n /**\n * @notice Function for a borrower to create a bid for a loan with Collateral.\n * @param _lendingToken The lending token asset requested to be borrowed.\n * @param _marketplaceId The unique id of the marketplace for the bid.\n * @param _principal The principal amount of the loan bid.\n * @param _duration The recurrent length of time before which a payment is due.\n * @param _APR The proposed interest rate for the loan bid.\n * @param _metadataURI The URI for additional borrower loan information as part of loan bid.\n * @param _receiver The address where the loan amount will be sent to.\n * @param _collateralInfo Additional information about the collateral asset.\n */\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver,\n Collateral[] calldata _collateralInfo\n ) external returns (uint256 bidId_);\n\n /**\n * @notice Function for a lender to accept a proposed loan bid.\n * @param _bidId The id of the loan bid to accept.\n */\n function lenderAcceptBid(uint256 _bidId)\n external\n returns (\n uint256 amountToProtocol,\n uint256 amountToMarketplace,\n uint256 amountToBorrower\n );\n\n /**\n * @notice Function for users to make the minimum amount due for an active loan.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanMinimum(uint256 _bidId) external;\n\n /**\n * @notice Function for users to repay an active loan in full.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanFull(uint256 _bidId) external;\n\n /**\n * @notice Function for users to make a payment towards an active loan.\n * @param _bidId The id of the loan to make the payment towards.\n * @param _amount The amount of the payment.\n */\n function repayLoan(uint256 _bidId, uint256 _amount) external;\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n */\n function isLoanDefaulted(uint256 _bidId) external view returns (bool);\n\n /**\n * @notice Checks to see if a loan was delinquent for longer than liquidation delay.\n * @param _bidId The id of the loan bid to check for.\n */\n function isLoanLiquidateable(uint256 _bidId) external view returns (bool);\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n */\n function isPaymentLate(uint256 _bidId) external view returns (bool);\n\n function getBidState(uint256 _bidId) external view returns (BidState);\n\n function getBorrowerActiveLoanIds(address _borrower)\n external\n view\n returns (uint256[] memory);\n\n /**\n * @notice Returns the borrower address for a given bid.\n * @param _bidId The id of the bid/loan to get the borrower for.\n * @return borrower_ The address of the borrower associated with the bid.\n */\n function getLoanBorrower(uint256 _bidId)\n external\n view\n returns (address borrower_);\n\n /**\n * @notice Returns the lender address for a given bid.\n * @param _bidId The id of the bid/loan to get the lender for.\n * @return lender_ The address of the lender associated with the bid.\n */\n function getLoanLender(uint256 _bidId)\n external\n view\n returns (address lender_);\n\n function getLoanLendingToken(uint256 _bidId)\n external\n view\n returns (address token_);\n\n function getLoanMarketId(uint256 _bidId) external view returns (uint256);\n\n function getLoanSummary(uint256 _bidId)\n external\n view\n returns (\n address borrower,\n address lender,\n uint256 marketId,\n address principalTokenAddress,\n uint256 principalAmount,\n uint32 acceptedTimestamp,\n uint32 lastRepaidTimestamp,\n BidState bidState\n );\n\n function calculateAmountOwed(uint256 _bidId, uint256 _timestamp)\n external\n view\n returns (Payment memory owed);\n\n function calculateAmountDue(uint256 _bidId, uint256 _timestamp)\n external\n view\n returns (Payment memory due);\n\n function lenderCloseLoan(uint256 _bidId) external;\n\n function lenderCloseLoanWithRecipient(uint256 _bidId, address _recipient)\n external;\n\n function liquidateLoanFull(uint256 _bidId) external;\n\n function liquidateLoanFullWithRecipient(uint256 _bidId, address _recipient)\n external;\n\n function getLoanDefaultTimestamp(uint256 _bidId)\n external\n view\n returns (uint256);\n\n\n function getEscrowVault() external view returns(address);\n\n\n // function isPauser(address _account) external view returns(bool);\n}\n" + }, + "contracts/interfaces/ITellerV2Autopay.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ITellerV2Autopay {\n function setAutoPayEnabled(uint256 _bidId, bool _autoPayEnabled) external;\n\n function autoPayLoanMinimum(uint256 _bidId) external;\n\n function initialize(uint16 _newFee, address _newOwner) external;\n\n function setAutopayFee(uint16 _newFee) external;\n}\n" + }, + "contracts/interfaces/ITellerV2Context.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ITellerV2Context {\n function setTrustedMarketForwarder(uint256 _marketId, address _forwarder)\n external;\n\n function approveMarketForwarder(uint256 _marketId, address _forwarder)\n external;\n}\n" + }, + "contracts/interfaces/ITellerV2MarketForwarder.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\nimport { Collateral } from \"./escrow/ICollateralEscrowV1.sol\";\n\ninterface ITellerV2MarketForwarder {\n struct CreateLoanArgs {\n uint256 marketId;\n address lendingToken;\n uint256 principal;\n uint32 duration;\n uint16 interestRate;\n string metadataURI;\n address recipient;\n Collateral[] collateral;\n }\n}\n" + }, + "contracts/interfaces/ITellerV2Storage.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ITellerV2Storage {\n function marketRegistry() external view returns (address);\n}\n" + }, + "contracts/interfaces/IUniswapPricingLibrary.sol": { + "content": "// SPDX-Licence-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\ninterface IUniswapPricingLibrary {\n \n\n struct PoolRouteConfig {\n address pool;\n bool zeroForOne;\n uint32 twapInterval;\n uint256 token0Decimals;\n uint256 token1Decimals;\n } \n\n\n\n function getUniswapPriceRatioForPoolRoutes(\n PoolRouteConfig[] memory poolRoutes\n ) external view returns (uint256 priceRatio);\n\n\n function getUniswapPriceRatioForPool(\n PoolRouteConfig memory poolRoute\n ) external view returns (uint256 priceRatio);\n\n}\n" + }, + "contracts/interfaces/uniswap/IUniswapV3Factory.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.8.0;\n\n/// @title The interface for the Uniswap V3 Factory\n/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees\ninterface IUniswapV3Factory {\n /// @notice Emitted when the owner of the factory is changed\n /// @param oldOwner The owner before the owner was changed\n /// @param newOwner The owner after the owner was changed\n event OwnerChanged(address indexed oldOwner, address indexed newOwner);\n\n /// @notice Emitted when a pool is created\n /// @param token0 The first token of the pool by address sort order\n /// @param token1 The second token of the pool by address sort order\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks\n /// @param pool The address of the created pool\n event PoolCreated(\n address indexed token0,\n address indexed token1,\n uint24 indexed fee,\n int24 tickSpacing,\n address pool\n );\n\n /// @notice Emitted when a new fee amount is enabled for pool creation via the factory\n /// @param fee The enabled fee, denominated in hundredths of a bip\n /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee\n event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);\n\n /// @notice Returns the current owner of the factory\n /// @dev Can be changed by the current owner via setOwner\n /// @return The address of the factory owner\n function owner() external view returns (address);\n\n /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled\n /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context\n /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee\n /// @return The tick spacing\n function feeAmountTickSpacing(uint24 fee) external view returns (int24);\n\n /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist\n /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order\n /// @param tokenA The contract address of either token0 or token1\n /// @param tokenB The contract address of the other token\n /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n /// @return pool The pool address\n function getPool(address tokenA, address tokenB, uint24 fee)\n external\n view\n returns (address pool);\n\n /// @notice Creates a pool for the given two tokens and fee\n /// @param tokenA One of the two tokens in the desired pool\n /// @param tokenB The other of the two tokens in the desired pool\n /// @param fee The desired fee for the pool\n /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved\n /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments\n /// are invalid.\n /// @return pool The address of the newly created pool\n function createPool(address tokenA, address tokenB, uint24 fee)\n external\n returns (address pool);\n\n /// @notice Updates the owner of the factory\n /// @dev Must be called by the current owner\n /// @param _owner The new owner of the factory\n function setOwner(address _owner) external;\n\n /// @notice Enables a fee amount with the given tickSpacing\n /// @dev Fee amounts may never be removed once enabled\n /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)\n /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount\n function enableFeeAmount(uint24 fee, int24 tickSpacing) external;\n}\n" + }, + "contracts/interfaces/uniswap/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport \"./pool/IUniswapV3PoolImmutables.sol\";\nimport \"./pool/IUniswapV3PoolState.sol\";\nimport \"./pool/IUniswapV3PoolDerivedState.sol\";\nimport \"./pool/IUniswapV3PoolActions.sol\";\nimport \"./pool/IUniswapV3PoolOwnerActions.sol\";\nimport \"./pool/IUniswapV3PoolEvents.sol\";\n\n/// @title The interface for a Uniswap V3 Pool\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\n/// to the ERC20 specification\n/// @dev The pool interface is broken up into many smaller pieces\ninterface IUniswapV3Pool is\n IUniswapV3PoolImmutables,\n IUniswapV3PoolState,\n IUniswapV3PoolDerivedState,\n IUniswapV3PoolActions,\n IUniswapV3PoolOwnerActions,\n IUniswapV3PoolEvents\n{\n\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissionless pool actions\n/// @notice Contains pool methods that can be called by anyone\ninterface IUniswapV3PoolActions {\n /// @notice Sets the initial price for the pool\n /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\n /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\n function initialize(uint160 sqrtPriceX96) external;\n\n /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\n /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\n /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\n /// on tickLower, tickUpper, the amount of liquidity, and the current price.\n /// @param recipient The address for which the liquidity will be created\n /// @param tickLower The lower tick of the position in which to add liquidity\n /// @param tickUpper The upper tick of the position in which to add liquidity\n /// @param amount The amount of liquidity to mint\n /// @param data Any data that should be passed through to the callback\n /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\n /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\n function mint(\n address recipient,\n int24 tickLower,\n int24 tickUpper,\n uint128 amount,\n bytes calldata data\n ) external returns (uint256 amount0, uint256 amount1);\n\n /// @notice Collects tokens owed to a position\n /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\n /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\n /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\n /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\n /// @param recipient The address which should receive the fees collected\n /// @param tickLower The lower tick of the position for which to collect fees\n /// @param tickUpper The upper tick of the position for which to collect fees\n /// @param amount0Requested How much token0 should be withdrawn from the fees owed\n /// @param amount1Requested How much token1 should be withdrawn from the fees owed\n /// @return amount0 The amount of fees collected in token0\n /// @return amount1 The amount of fees collected in token1\n function collect(\n address recipient,\n int24 tickLower,\n int24 tickUpper,\n uint128 amount0Requested,\n uint128 amount1Requested\n ) external returns (uint128 amount0, uint128 amount1);\n\n /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\n /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\n /// @dev Fees must be collected separately via a call to #collect\n /// @param tickLower The lower tick of the position for which to burn liquidity\n /// @param tickUpper The upper tick of the position for which to burn liquidity\n /// @param amount How much liquidity to burn\n /// @return amount0 The amount of token0 sent to the recipient\n /// @return amount1 The amount of token1 sent to the recipient\n function burn(int24 tickLower, int24 tickUpper, uint128 amount)\n external\n returns (uint256 amount0, uint256 amount1);\n\n /// @notice Swap token0 for token1, or token1 for token0\n /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\n /// @param recipient The address to receive the output of the swap\n /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\n /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\n /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\n /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\n /// @param data Any data to be passed through to the callback\n /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\n /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n\n /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\n /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\n /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\n /// with 0 amount{0,1} and sending the donation amount(s) from the callback\n /// @param recipient The address which will receive the token0 and token1 amounts\n /// @param amount0 The amount of token0 to send\n /// @param amount1 The amount of token1 to send\n /// @param data Any data to be passed through to the callback\n function flash(\n address recipient,\n uint256 amount0,\n uint256 amount1,\n bytes calldata data\n ) external;\n\n /// @notice Increase the maximum number of price and liquidity observations that this pool will store\n /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\n /// the input observationCardinalityNext.\n /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\n function increaseObservationCardinalityNext(\n uint16 observationCardinalityNext\n ) external;\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolDerivedState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that is not stored\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\n/// blockchain. The functions here may have variable gas costs.\ninterface IUniswapV3PoolDerivedState {\n /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\n /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\n /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\n /// you must call it with secondsAgos = [3600, 0].\n /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\n /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\n /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\n /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\n /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\n /// timestamp\n function observe(uint32[] calldata secondsAgos)\n external\n view\n returns (\n int56[] memory tickCumulatives,\n uint160[] memory secondsPerLiquidityCumulativeX128s\n );\n\n /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\n /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\n /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\n /// snapshot is taken and the second snapshot is taken.\n /// @param tickLower The lower tick of the range\n /// @param tickUpper The upper tick of the range\n /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\n /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\n /// @return secondsInside The snapshot of seconds per liquidity for the range\n function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\n external\n view\n returns (\n int56 tickCumulativeInside,\n uint160 secondsPerLiquidityInsideX128,\n uint32 secondsInside\n );\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolEvents.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Events emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolEvents {\n /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\n /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\n /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\n /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\n event Initialize(uint160 sqrtPriceX96, int24 tick);\n\n /// @notice Emitted when liquidity is minted for a given position\n /// @param sender The address that minted the liquidity\n /// @param owner The owner of the position and recipient of any minted liquidity\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount The amount of liquidity minted to the position range\n /// @param amount0 How much token0 was required for the minted liquidity\n /// @param amount1 How much token1 was required for the minted liquidity\n event Mint(\n address sender,\n address indexed owner,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount,\n uint256 amount0,\n uint256 amount1\n );\n\n /// @notice Emitted when fees are collected by the owner of a position\n /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\n /// @param owner The owner of the position for which fees are collected\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount0 The amount of token0 fees collected\n /// @param amount1 The amount of token1 fees collected\n event Collect(\n address indexed owner,\n address recipient,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount0,\n uint128 amount1\n );\n\n /// @notice Emitted when a position's liquidity is removed\n /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\n /// @param owner The owner of the position for which liquidity is removed\n /// @param tickLower The lower tick of the position\n /// @param tickUpper The upper tick of the position\n /// @param amount The amount of liquidity to remove\n /// @param amount0 The amount of token0 withdrawn\n /// @param amount1 The amount of token1 withdrawn\n event Burn(\n address indexed owner,\n int24 indexed tickLower,\n int24 indexed tickUpper,\n uint128 amount,\n uint256 amount0,\n uint256 amount1\n );\n\n /// @notice Emitted by the pool for any swaps between token0 and token1\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param recipient The address that received the output of the swap\n /// @param amount0 The delta of the token0 balance of the pool\n /// @param amount1 The delta of the token1 balance of the pool\n /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\n /// @param liquidity The liquidity of the pool after the swap\n /// @param tick The log base 1.0001 of price of the pool after the swap\n event Swap(\n address indexed sender,\n address indexed recipient,\n int256 amount0,\n int256 amount1,\n uint160 sqrtPriceX96,\n uint128 liquidity,\n int24 tick\n );\n\n /// @notice Emitted by the pool for any flashes of token0/token1\n /// @param sender The address that initiated the swap call, and that received the callback\n /// @param recipient The address that received the tokens from flash\n /// @param amount0 The amount of token0 that was flashed\n /// @param amount1 The amount of token1 that was flashed\n /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\n /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\n event Flash(\n address indexed sender,\n address indexed recipient,\n uint256 amount0,\n uint256 amount1,\n uint256 paid0,\n uint256 paid1\n );\n\n /// @notice Emitted by the pool for increases to the number of observations that can be stored\n /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\n /// just before a mint/swap/burn.\n /// @param observationCardinalityNextOld The previous value of the next observation cardinality\n /// @param observationCardinalityNextNew The updated value of the next observation cardinality\n event IncreaseObservationCardinalityNext(\n uint16 observationCardinalityNextOld,\n uint16 observationCardinalityNextNew\n );\n\n /// @notice Emitted when the protocol fee is changed by the pool\n /// @param feeProtocol0Old The previous value of the token0 protocol fee\n /// @param feeProtocol1Old The previous value of the token1 protocol fee\n /// @param feeProtocol0New The updated value of the token0 protocol fee\n /// @param feeProtocol1New The updated value of the token1 protocol fee\n event SetFeeProtocol(\n uint8 feeProtocol0Old,\n uint8 feeProtocol1Old,\n uint8 feeProtocol0New,\n uint8 feeProtocol1New\n );\n\n /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\n /// @param sender The address that collects the protocol fees\n /// @param recipient The address that receives the collected protocol fees\n /// @param amount0 The amount of token0 protocol fees that is withdrawn\n /// @param amount0 The amount of token1 protocol fees that is withdrawn\n event CollectProtocol(\n address indexed sender,\n address indexed recipient,\n uint128 amount0,\n uint128 amount1\n );\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolImmutables.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that never changes\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\ninterface IUniswapV3PoolImmutables {\n /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\n /// @return The contract address\n function factory() external view returns (address);\n\n /// @notice The first of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token0() external view returns (address);\n\n /// @notice The second of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token1() external view returns (address);\n\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\n /// @return The fee\n function fee() external view returns (uint24);\n\n /// @notice The pool tick spacing\n /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\n /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\n /// This value is an int24 to avoid casting even though it is always positive.\n /// @return The tick spacing\n function tickSpacing() external view returns (int24);\n\n /// @notice The maximum amount of position liquidity that can use any tick in the range\n /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\n /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\n /// @return The max amount of liquidity per tick\n function maxLiquidityPerTick() external view returns (uint128);\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolOwnerActions.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissioned pool actions\n/// @notice Contains pool methods that may only be called by the factory owner\ninterface IUniswapV3PoolOwnerActions {\n /// @notice Set the denominator of the protocol's % share of the fees\n /// @param feeProtocol0 new protocol fee for token0 of the pool\n /// @param feeProtocol1 new protocol fee for token1 of the pool\n function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\n\n /// @notice Collect the protocol fee accrued to the pool\n /// @param recipient The address to which collected protocol fees should be sent\n /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\n /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\n /// @return amount0 The protocol fee collected in token0\n /// @return amount1 The protocol fee collected in token1\n function collectProtocol(\n address recipient,\n uint128 amount0Requested,\n uint128 amount1Requested\n ) external returns (uint128 amount0, uint128 amount1);\n}\n" + }, + "contracts/interfaces/uniswap/pool/IUniswapV3PoolState.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that can change\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\n/// per transaction\ninterface IUniswapV3PoolState {\n /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\n /// when accessed externally.\n /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\n /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\n /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\n /// boundary.\n /// observationIndex The index of the last oracle observation that was written,\n /// observationCardinality The current maximum number of observations stored in the pool,\n /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\n /// feeProtocol The protocol fee for both tokens of the pool.\n /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\n /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\n /// unlocked Whether the pool is currently locked to reentrancy\n function slot0()\n external\n view\n returns (\n uint160 sqrtPriceX96,\n int24 tick,\n uint16 observationIndex,\n uint16 observationCardinality,\n uint16 observationCardinalityNext,\n uint8 feeProtocol,\n bool unlocked\n );\n\n /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\n /// @dev This value can overflow the uint256\n function feeGrowthGlobal0X128() external view returns (uint256);\n\n /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\n /// @dev This value can overflow the uint256\n function feeGrowthGlobal1X128() external view returns (uint256);\n\n /// @notice The amounts of token0 and token1 that are owed to the protocol\n /// @dev Protocol fees will never exceed uint128 max in either token\n function protocolFees()\n external\n view\n returns (uint128 token0, uint128 token1);\n\n /// @notice The currently in range liquidity available to the pool\n /// @dev This value has no relationship to the total liquidity across all ticks\n function liquidity() external view returns (uint128);\n\n /// @notice Look up information about a specific tick in the pool\n /// @param tick The tick to look up\n /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\n /// tick upper,\n /// liquidityNet how much liquidity changes when the pool price crosses the tick,\n /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\n /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\n /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\n /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\n /// secondsOutside the seconds spent on the other side of the tick from the current tick,\n /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\n /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\n /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\n /// a specific position.\n function ticks(int24 tick)\n external\n view\n returns (\n uint128 liquidityGross,\n int128 liquidityNet,\n uint256 feeGrowthOutside0X128,\n uint256 feeGrowthOutside1X128,\n int56 tickCumulativeOutside,\n uint160 secondsPerLiquidityOutsideX128,\n uint32 secondsOutside,\n bool initialized\n );\n\n /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\n function tickBitmap(int16 wordPosition) external view returns (uint256);\n\n /// @notice Returns the information about a position by the position's key\n /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\n /// @return _liquidity The amount of liquidity in the position,\n /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\n /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\n /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\n /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\n function positions(bytes32 key)\n external\n view\n returns (\n uint128 _liquidity,\n uint256 feeGrowthInside0LastX128,\n uint256 feeGrowthInside1LastX128,\n uint128 tokensOwed0,\n uint128 tokensOwed1\n );\n\n /// @notice Returns data about a specific observation index\n /// @param index The element of the observations array to fetch\n /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\n /// ago, rather than at a specific index in the array.\n /// @return blockTimestamp The timestamp of the observation,\n /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\n /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\n /// Returns initialized whether the observation has been initialized and the values are safe to use\n function observations(uint256 index)\n external\n view\n returns (\n uint32 blockTimestamp,\n int56 tickCumulative,\n uint160 secondsPerLiquidityCumulativeX128,\n bool initialized\n );\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/CommitmentRolloverLoan.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/ICommitmentRolloverLoan.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\ncontract CommitmentRolloverLoan is ICommitmentRolloverLoan {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ILenderCommitmentForwarder public immutable LENDER_COMMITMENT_FORWARDER;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _tellerV2, address _lenderCommitmentForwarder) {\n TELLER_V2 = ITellerV2(_tellerV2);\n LENDER_COMMITMENT_FORWARDER = ILenderCommitmentForwarder(\n _lenderCommitmentForwarder\n );\n }\n\n /**\n * @notice Allows a borrower to rollover a loan to a new commitment.\n * @param _loanId The ID of the existing loan.\n * @param _rolloverAmount The amount to rollover.\n * @param _commitmentArgs Arguments for the commitment to accept.\n * @return newLoanId_ The ID of the new loan created by accepting the commitment.\n */\n function rolloverLoan(\n uint256 _loanId,\n uint256 _rolloverAmount,\n AcceptCommitmentArgs calldata _commitmentArgs\n ) external returns (uint256 newLoanId_) {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n IERC20Upgradeable lendingToken = IERC20Upgradeable(\n TELLER_V2.getLoanLendingToken(_loanId)\n );\n uint256 balanceBefore = lendingToken.balanceOf(address(this));\n\n if (_rolloverAmount > 0) {\n //accept funds from the borrower to this contract\n lendingToken.transferFrom(borrower, address(this), _rolloverAmount);\n }\n\n // Accept commitment and receive funds to this contract\n newLoanId_ = _acceptCommitment(_commitmentArgs);\n\n // Calculate funds received\n uint256 fundsReceived = lendingToken.balanceOf(address(this)) -\n balanceBefore;\n\n // Approve TellerV2 to spend funds and repay loan\n lendingToken.approve(address(TELLER_V2), fundsReceived);\n TELLER_V2.repayLoanFull(_loanId);\n\n uint256 fundsRemaining = lendingToken.balanceOf(address(this)) -\n balanceBefore;\n\n if (fundsRemaining > 0) {\n lendingToken.transfer(borrower, fundsRemaining);\n }\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n * @return _amount The calculated amount, positive if borrower needs to send funds and negative if they will receive funds.\n */\n function calculateRolloverAmount(\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint256 _timestamp\n ) external view returns (int256 _amount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n _amount +=\n int256(repayAmountOwed.principal) +\n int256(repayAmountOwed.interest);\n\n uint256 _marketId = _getMarketIdForCommitment(\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 amountToBorrower = commitmentPrincipalRequested -\n amountToProtocol -\n amountToMarketplace;\n\n _amount -= int256(amountToBorrower);\n }\n\n /**\n * @notice Internally accepts a commitment via the `LENDER_COMMITMENT_FORWARDER`.\n * @param _commitmentArgs Arguments required to accept a commitment.\n * @return bidId_ The ID of the bid associated with the accepted commitment.\n */\n function _acceptCommitment(AcceptCommitmentArgs calldata _commitmentArgs)\n internal\n returns (uint256 bidId_)\n {\n bytes memory responseData = address(LENDER_COMMITMENT_FORWARDER)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n msg.sender\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return LENDER_COMMITMENT_FORWARDER.getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/ExtensionsContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/IExtensionsContext.sol\";\nimport \"@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\nabstract contract ExtensionsContextUpgradeable is IExtensionsContext {\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private userExtensions;\n\n event ExtensionAdded(address extension, address sender);\n event ExtensionRevoked(address extension, address sender);\n\n function hasExtension(address account, address extension)\n public\n view\n returns (bool)\n {\n return userExtensions[account][extension];\n }\n\n function addExtension(address extension) external {\n require(\n _msgSender() != extension,\n \"ExtensionsContextUpgradeable: cannot approve own extension\"\n );\n\n userExtensions[_msgSender()][extension] = true;\n emit ExtensionAdded(extension, _msgSender());\n }\n\n function revokeExtension(address extension) external {\n userExtensions[_msgSender()][extension] = false;\n emit ExtensionRevoked(extension, _msgSender());\n }\n\n function _msgSender() internal view virtual returns (address sender) {\n address sender;\n\n if (msg.data.length >= 20) {\n assembly {\n sender := shr(96, calldataload(sub(calldatasize(), 20)))\n }\n\n if (hasExtension(sender, msg.sender)) {\n return sender;\n }\n }\n\n return msg.sender;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\n//https://docs.aave.com/developers/v/1.0/tutorials/performing-a-flash-loan/...-in-your-project\n\ncontract FlashRolloverLoan_G1 is IFlashLoanSimpleReceiver, IFlashRolloverLoan {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ILenderCommitmentForwarder public immutable LENDER_COMMITMENT_FORWARDER;\n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _lenderCommitmentForwarder,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n LENDER_COMMITMENT_FORWARDER = ILenderCommitmentForwarder(\n _lenderCommitmentForwarder\n );\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /*\n need to pass loanId and borrower \n */\n\n /**\n * @notice Allows a borrower to rollover a loan to a new commitment.\n * @param _loanId The bid id for the loan to repay\n * @param _flashLoanAmount The amount to flash borrow.\n * @param _acceptCommitmentArgs Arguments for the commitment to accept.\n * @return newLoanId_ The ID of the new loan created by accepting the commitment.\n */\n\n /*\n \nThe flash loan amount can naively be the exact amount needed to repay the old loan \n\nIf the new loan pays out (after fees) MORE than the aave loan amount+ fee) then borrower amount can be zero \n\n 1) I could solve for what the new loans payout (before fees and after fees) would NEED to be to make borrower amount 0...\n\n*/\n\n function rolloverLoanWithFlash(\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external returns (uint256 newLoanId_) {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /*\n Notice: If collateral is being rolled over, it needs to be pre-approved from the borrower to the collateral manager \n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n * @notice Internally accepts a commitment via the `LENDER_COMMITMENT_FORWARDER`.\n * @param _commitmentArgs Arguments required to accept a commitment.\n * @return bidId_ The ID of the bid associated with the accepted commitment.\n */\n function _acceptCommitment(\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n bytes memory responseData = address(LENDER_COMMITMENT_FORWARDER)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\n// Interfaces\nimport \"./FlashRolloverLoan_G1.sol\";\n\ncontract FlashRolloverLoan_G2 is FlashRolloverLoan_G1 {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _lenderCommitmentForwarder,\n address _poolAddressesProvider\n )\n FlashRolloverLoan_G1(\n _tellerV2,\n _lenderCommitmentForwarder,\n _poolAddressesProvider\n )\n {}\n\n /*\n\n This assumes that the flash amount will be the repayLoanFull amount !!\n\n */\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return LENDER_COMMITMENT_FORWARDER.getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\ncontract FlashRolloverLoan_G3 is IFlashLoanSimpleReceiver, IFlashRolloverLoan {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ILenderCommitmentForwarder public immutable LENDER_COMMITMENT_FORWARDER;\n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n * @param _lenderCommitmentForwarder The address of the LenderCommitmentForwarder contract.\n * @param _poolAddressesProvider The address of the PoolAddressesProvider.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _lenderCommitmentForwarder,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n LENDER_COMMITMENT_FORWARDER = ILenderCommitmentForwarder(\n _lenderCommitmentForwarder\n );\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /**\n *\n * @notice Allows the borrower to rollover their existing loan using a flash loan mechanism.\n * The borrower might also provide an additional amount during the rollover.\n *\n * @dev The function first verifies that the caller is the borrower of the loan.\n * It then optionally transfers the additional amount specified by the borrower.\n * A flash loan is then taken from the pool to facilitate the rollover and\n * a callback is executed for further operations.\n *\n * @param _loanId Identifier of the existing loan to be rolled over.\n * @param _flashLoanAmount Amount of flash loan to be borrowed for the rollover.\n * @param _borrowerAmount Additional amount that the borrower may want to add during rollover.\n * @param _acceptCommitmentArgs Commitment arguments that might be necessary for internal operations.\n *\n * @return newLoanId_ Identifier of the new loan post rollover.\n */\n function rolloverLoanWithFlash(\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external returns (uint256 newLoanId_) {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /**\n *\n * @notice Callback function that is triggered by Aave during the flash loan process.\n * This function handles the logic to use the borrowed funds to rollover the loan,\n * make necessary repayments, and manage the loan commitments.\n *\n * @dev The function ensures the initiator is this contract, decodes the data provided by\n * the flash loan call, repays the original loan in full, accepts new loan commitments,\n * approves the repayment for the flash loan and then handles any remaining funds.\n * This function should only be called by the FlashLoanPool as ensured by the `onlyFlashLoanPool` modifier.\n *\n * @param _flashToken The token in which the flash loan is borrowed.\n * @param _flashAmount The amount of tokens borrowed via the flash loan.\n * @param _flashFees The fees associated with the flash loan to be repaid to Aave.\n * @param _initiator The address initiating the flash loan (must be this contract).\n * @param _data Encoded data containing necessary information for loan rollover.\n *\n * @return Returns true if the operation was successful.\n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address _initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n _initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n /**\n *\n *\n * @notice Internal function that repays a loan in full on behalf of this contract.\n *\n * @dev The function first calculates the funds held by the contract before repayment, then approves\n * the repayment amount to the TellerV2 contract and finally repays the loan in full.\n *\n * @param _bidId Identifier of the loan to be repaid.\n * @param _principalToken The token in which the loan was originated.\n * @param _repayAmount The amount to be repaid.\n *\n * @return repayAmount_ The actual amount that was used for repayment.\n */\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n *\n *\n * @notice Accepts a loan commitment using either a Merkle proof or standard method.\n *\n * @dev The function first checks if a Merkle proof is provided, based on which it calls the relevant\n * `acceptCommitment` function in the LenderCommitmentForwarder contract.\n *\n * @param borrower The address of the borrower for whom the commitment is being accepted.\n * @param principalToken The token in which the loan is being accepted.\n * @param _commitmentArgs The arguments necessary for accepting the commitment.\n *\n * @return bidId_ Identifier of the accepted loan.\n * @return acceptCommitmentAmount_ The amount received from accepting the commitment.\n */\n function _acceptCommitment(\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n bool usingMerkleProof = _commitmentArgs.merkleProof.length > 0;\n\n if (usingMerkleProof) {\n bytes memory responseData = address(LENDER_COMMITMENT_FORWARDER)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipientAndProof\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration,\n _commitmentArgs.merkleProof\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n } else {\n bytes memory responseData = address(LENDER_COMMITMENT_FORWARDER)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return LENDER_COMMITMENT_FORWARDER.getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G4.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan_G4.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\ncontract FlashRolloverLoan_G4 is IFlashLoanSimpleReceiver, IFlashRolloverLoan_G4 {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n \n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n * @param _lenderCommitmentForwarder The address of the LenderCommitmentForwarder contract.\n * @param _poolAddressesProvider The address of the PoolAddressesProvider.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /**\n *\n * @notice Allows the borrower to rollover their existing loan using a flash loan mechanism.\n * The borrower might also provide an additional amount during the rollover.\n *\n * @dev The function first verifies that the caller is the borrower of the loan.\n * It then optionally transfers the additional amount specified by the borrower.\n * A flash loan is then taken from the pool to facilitate the rollover and\n * a callback is executed for further operations.\n *\n * @param _loanId Identifier of the existing loan to be rolled over.\n * @param _flashLoanAmount Amount of flash loan to be borrowed for the rollover.\n * @param _borrowerAmount Additional amount that the borrower may want to add during rollover.\n * @param _acceptCommitmentArgs Commitment arguments that might be necessary for internal operations.\n *\n * @return newLoanId_ Identifier of the new loan post rollover.\n */\n function rolloverLoanWithFlash(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external returns (uint256 newLoanId_) {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n lenderCommitmentForwarder :_lenderCommitmentForwarder,\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /**\n *\n * @notice Callback function that is triggered by Aave during the flash loan process.\n * This function handles the logic to use the borrowed funds to rollover the loan,\n * make necessary repayments, and manage the loan commitments.\n *\n * @dev The function ensures the initiator is this contract, decodes the data provided by\n * the flash loan call, repays the original loan in full, accepts new loan commitments,\n * approves the repayment for the flash loan and then handles any remaining funds.\n * This function should only be called by the FlashLoanPool as ensured by the `onlyFlashLoanPool` modifier.\n *\n * @param _flashToken The token in which the flash loan is borrowed.\n * @param _flashAmount The amount of tokens borrowed via the flash loan.\n * @param _flashFees The fees associated with the flash loan to be repaid to Aave.\n * @param _initiator The address initiating the flash loan (must be this contract).\n * @param _data Encoded data containing necessary information for loan rollover.\n *\n * @return Returns true if the operation was successful.\n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address _initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n _initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.lenderCommitmentForwarder,\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n /**\n *\n *\n * @notice Internal function that repays a loan in full on behalf of this contract.\n *\n * @dev The function first calculates the funds held by the contract before repayment, then approves\n * the repayment amount to the TellerV2 contract and finally repays the loan in full.\n *\n * @param _bidId Identifier of the loan to be repaid.\n * @param _principalToken The token in which the loan was originated.\n * @param _repayAmount The amount to be repaid.\n *\n * @return repayAmount_ The actual amount that was used for repayment.\n */\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n *\n *\n * @notice Accepts a loan commitment using either a Merkle proof or standard method.\n *\n * @dev The function first checks if a Merkle proof is provided, based on which it calls the relevant\n * `acceptCommitment` function in the LenderCommitmentForwarder contract.\n *\n * @param borrower The address of the borrower for whom the commitment is being accepted.\n * @param principalToken The token in which the loan is being accepted.\n * @param _commitmentArgs The arguments necessary for accepting the commitment.\n *\n * @return bidId_ Identifier of the accepted loan.\n * @return acceptCommitmentAmount_ The amount received from accepting the commitment.\n */\n function _acceptCommitment(\n address lenderCommitmentForwarder,\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n bool usingMerkleProof = _commitmentArgs.merkleProof.length > 0;\n\n if (usingMerkleProof) {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipientAndProof\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration,\n _commitmentArgs.merkleProof\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n } else {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(_lenderCommitmentForwarder,\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(address _lenderCommitmentForwarder, uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return ILenderCommitmentForwarder(_lenderCommitmentForwarder).getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}\n \n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G5.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/ISmartCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan_G4.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\ncontract FlashRolloverLoan_G5 is IFlashLoanSimpleReceiver, IFlashRolloverLoan_G4 {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n \n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n address smartCommitmentAddress; //if this is not address(0), we will use this ! leave empty if not used. \n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n * @param _lenderCommitmentForwarder The address of the LenderCommitmentForwarder contract.\n * @param _poolAddressesProvider The address of the PoolAddressesProvider.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /**\n *\n * @notice Allows the borrower to rollover their existing loan using a flash loan mechanism.\n * The borrower might also provide an additional amount during the rollover.\n *\n * @dev The function first verifies that the caller is the borrower of the loan.\n * It then optionally transfers the additional amount specified by the borrower.\n * A flash loan is then taken from the pool to facilitate the rollover and\n * a callback is executed for further operations.\n *\n * @param _loanId Identifier of the existing loan to be rolled over.\n * @param _flashLoanAmount Amount of flash loan to be borrowed for the rollover.\n * @param _borrowerAmount Additional amount that the borrower may want to add during rollover.\n * @param _acceptCommitmentArgs Commitment arguments that might be necessary for internal operations.\n * \n */\n function rolloverLoanWithFlash(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n lenderCommitmentForwarder :_lenderCommitmentForwarder,\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /**\n *\n * @notice Callback function that is triggered by Aave during the flash loan process.\n * This function handles the logic to use the borrowed funds to rollover the loan,\n * make necessary repayments, and manage the loan commitments.\n *\n * @dev The function ensures the initiator is this contract, decodes the data provided by\n * the flash loan call, repays the original loan in full, accepts new loan commitments,\n * approves the repayment for the flash loan and then handles any remaining funds.\n * This function should only be called by the FlashLoanPool as ensured by the `onlyFlashLoanPool` modifier.\n *\n * @param _flashToken The token in which the flash loan is borrowed.\n * @param _flashAmount The amount of tokens borrowed via the flash loan.\n * @param _flashFees The fees associated with the flash loan to be repaid to Aave.\n * @param _initiator The address initiating the flash loan (must be this contract).\n * @param _data Encoded data containing necessary information for loan rollover.\n *\n * @return Returns true if the operation was successful.\n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address _initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n _initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.lenderCommitmentForwarder,\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n /**\n *\n *\n * @notice Internal function that repays a loan in full on behalf of this contract.\n *\n * @dev The function first calculates the funds held by the contract before repayment, then approves\n * the repayment amount to the TellerV2 contract and finally repays the loan in full.\n *\n * @param _bidId Identifier of the loan to be repaid.\n * @param _principalToken The token in which the loan was originated.\n * @param _repayAmount The amount to be repaid.\n *\n * @return repayAmount_ The actual amount that was used for repayment.\n */\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n *\n *\n * @notice Accepts a loan commitment using either a Merkle proof or standard method.\n *\n * @dev The function first checks if a Merkle proof is provided, based on which it calls the relevant\n * `acceptCommitment` function in the LenderCommitmentForwarder contract.\n *\n * @param borrower The address of the borrower for whom the commitment is being accepted.\n * @param principalToken The token in which the loan is being accepted.\n * @param _commitmentArgs The arguments necessary for accepting the commitment.\n *\n * @return bidId_ Identifier of the accepted loan.\n * @return acceptCommitmentAmount_ The amount received from accepting the commitment.\n */\n function _acceptCommitment(\n address lenderCommitmentForwarder,\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n\n\n if (_commitmentArgs.smartCommitmentAddress != address(0)) {\n\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ISmartCommitmentForwarder\n .acceptSmartCommitmentWithRecipient\n .selector,\n _commitmentArgs.smartCommitmentAddress,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n\n }else { \n\n bool usingMerkleProof = _commitmentArgs.merkleProof.length > 0;\n\n if (usingMerkleProof) {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipientAndProof\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration,\n _commitmentArgs.merkleProof\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n } else {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n }\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(_lenderCommitmentForwarder,\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(address _lenderCommitmentForwarder, uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return ILenderCommitmentForwarder(_lenderCommitmentForwarder).getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan_G6.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../interfaces/ITellerV2.sol\";\nimport \"../../interfaces/IProtocolFee.sol\";\nimport \"../../interfaces/ITellerV2Storage.sol\";\nimport \"../../interfaces/IMarketRegistry.sol\";\nimport \"../../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../../interfaces/ISmartCommitmentForwarder.sol\";\nimport \"../../interfaces/IFlashRolloverLoan_G6.sol\";\nimport \"../../libraries/NumbersLib.sol\";\n\nimport { IPool } from \"../../interfaces/aave/IPool.sol\";\nimport { IFlashLoanSimpleReceiver } from \"../../interfaces/aave/IFlashLoanSimpleReceiver.sol\";\nimport { IPoolAddressesProvider } from \"../../interfaces/aave/IPoolAddressesProvider.sol\";\n\n\n\n/*\n G6: Additionally incorporates referral rewards \n*/\n\n\ncontract FlashRolloverLoan_G6 is IFlashLoanSimpleReceiver, IFlashRolloverLoan_G6 {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n \n\n address public immutable POOL_ADDRESSES_PROVIDER;\n\n event RolloverLoanComplete(\n address borrower,\n uint256 originalLoanId,\n uint256 newLoanId,\n uint256 fundsRemaining\n );\n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n address smartCommitmentAddress; //if this is not address(0), we will use this ! leave empty if not used. \n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n * @param _lenderCommitmentForwarder The address of the LenderCommitmentForwarder contract.\n * @param _poolAddressesProvider The address of the PoolAddressesProvider.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n POOL_ADDRESSES_PROVIDER = _poolAddressesProvider;\n }\n\n modifier onlyFlashLoanPool() {\n require(\n msg.sender == address(POOL()),\n \"FlashRolloverLoan: Must be called by FlashLoanPool\"\n );\n\n _;\n }\n\n /**\n *\n * @notice Allows the borrower to rollover their existing loan using a flash loan mechanism.\n * The borrower might also provide an additional amount during the rollover.\n *\n * @dev The function first verifies that the caller is the borrower of the loan.\n * It then optionally transfers the additional amount specified by the borrower.\n * A flash loan is then taken from the pool to facilitate the rollover and\n * a callback is executed for further operations.\n *\n * @param _loanId Identifier of the existing loan to be rolled over.\n * @param _flashLoanAmount Amount of flash loan to be borrowed for the rollover.\n * @param _borrowerAmount Additional amount that the borrower may want to add during rollover.\n * @param _acceptCommitmentArgs Commitment arguments that might be necessary for internal operations.\n * \n */\n function rolloverLoanWithFlash(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n uint256 _flashLoanAmount,\n uint256 _borrowerAmount, //an additional amount borrower may have to add\n uint256 _rewardAmount,\n address _rewardRecipient,\n AcceptCommitmentArgs calldata _acceptCommitmentArgs\n ) external {\n address borrower = TELLER_V2.getLoanBorrower(_loanId);\n require(borrower == msg.sender, \"CommitmentRolloverLoan: not borrower\");\n\n // Get lending token and balance before\n address lendingToken = TELLER_V2.getLoanLendingToken(_loanId);\n\n require( _rewardAmount <= _flashLoanAmount/ 10, \"Reward amount may only be up to 1/10 of flash loan amount\" );\n\n if (_borrowerAmount > 0) {\n IERC20(lendingToken).transferFrom(\n borrower,\n address(this),\n _borrowerAmount\n );\n }\n\n // Call 'Flash' on the vault to borrow funds and call tellerV2FlashCallback\n // This ultimately calls executeOperation\n IPool(POOL()).flashLoanSimple(\n address(this),\n lendingToken,\n _flashLoanAmount,\n abi.encode(\n RolloverCallbackArgs({\n lenderCommitmentForwarder :_lenderCommitmentForwarder,\n loanId: _loanId,\n borrower: borrower,\n borrowerAmount: _borrowerAmount,\n rewardRecipient: _rewardRecipient,\n rewardAmount: _rewardAmount,\n acceptCommitmentArgs: abi.encode(_acceptCommitmentArgs)\n })\n ),\n 0 //referral code\n );\n }\n\n /**\n *\n * @notice Callback function that is triggered by Aave during the flash loan process.\n * This function handles the logic to use the borrowed funds to rollover the loan,\n * make necessary repayments, and manage the loan commitments.\n *\n * @dev The function ensures the initiator is this contract, decodes the data provided by\n * the flash loan call, repays the original loan in full, accepts new loan commitments,\n * approves the repayment for the flash loan and then handles any remaining funds.\n * This function should only be called by the FlashLoanPool as ensured by the `onlyFlashLoanPool` modifier.\n *\n * @param _flashToken The token in which the flash loan is borrowed.\n * @param _flashAmount The amount of tokens borrowed via the flash loan.\n * @param _flashFees The fees associated with the flash loan to be repaid to Aave.\n * @param _initiator The address initiating the flash loan (must be this contract).\n * @param _data Encoded data containing necessary information for loan rollover.\n *\n * @return Returns true if the operation was successful.\n */\n function executeOperation(\n address _flashToken,\n uint256 _flashAmount,\n uint256 _flashFees,\n address _initiator,\n bytes calldata _data\n ) external virtual onlyFlashLoanPool returns (bool) {\n require(\n _initiator == address(this),\n \"This contract must be the initiator\"\n );\n\n RolloverCallbackArgs memory _rolloverArgs = abi.decode(\n _data,\n (RolloverCallbackArgs)\n );\n\n uint256 repaymentAmount = _repayLoanFull(\n _rolloverArgs.loanId,\n _flashToken,\n _flashAmount\n );\n\n AcceptCommitmentArgs memory acceptCommitmentArgs = abi.decode(\n _rolloverArgs.acceptCommitmentArgs,\n (AcceptCommitmentArgs)\n );\n\n // Accept commitment and receive funds to this contract\n\n (uint256 newLoanId, uint256 acceptCommitmentAmount) = _acceptCommitment(\n _rolloverArgs.lenderCommitmentForwarder,\n _rolloverArgs.borrower,\n _flashToken,\n acceptCommitmentArgs\n );\n\n //approve the repayment for the flash loan\n IERC20Upgradeable(_flashToken).approve(\n address(POOL()),\n _flashAmount + _flashFees\n );\n\n uint256 fundsRemaining = acceptCommitmentAmount +\n _rolloverArgs.borrowerAmount -\n repaymentAmount -\n _flashFees;\n\n if (fundsRemaining > 0) {\n\n if (_rolloverArgs.rewardAmount > 0){\n\n //make sure reward amount isnt TOO much here ? \n\n fundsRemaining -= _rolloverArgs.rewardAmount;\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.rewardRecipient,\n _rolloverArgs.rewardAmount\n );\n\n }\n\n IERC20Upgradeable(_flashToken).transfer(\n _rolloverArgs.borrower,\n fundsRemaining\n );\n }\n\n emit RolloverLoanComplete(\n _rolloverArgs.borrower,\n _rolloverArgs.loanId,\n newLoanId,\n fundsRemaining\n );\n\n return true;\n }\n\n /**\n *\n *\n * @notice Internal function that repays a loan in full on behalf of this contract.\n *\n * @dev The function first calculates the funds held by the contract before repayment, then approves\n * the repayment amount to the TellerV2 contract and finally repays the loan in full.\n *\n * @param _bidId Identifier of the loan to be repaid.\n * @param _principalToken The token in which the loan was originated.\n * @param _repayAmount The amount to be repaid.\n *\n * @return repayAmount_ The actual amount that was used for repayment.\n */\n function _repayLoanFull(\n uint256 _bidId,\n address _principalToken,\n uint256 _repayAmount\n ) internal returns (uint256 repayAmount_) {\n uint256 fundsBeforeRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n IERC20Upgradeable(_principalToken).approve(\n address(TELLER_V2),\n _repayAmount\n );\n TELLER_V2.repayLoanFull(_bidId);\n\n uint256 fundsAfterRepayment = IERC20Upgradeable(_principalToken)\n .balanceOf(address(this));\n\n repayAmount_ = fundsBeforeRepayment - fundsAfterRepayment;\n }\n\n /**\n *\n *\n * @notice Accepts a loan commitment using either a Merkle proof or standard method.\n *\n * @dev The function first checks if a Merkle proof is provided, based on which it calls the relevant\n * `acceptCommitment` function in the LenderCommitmentForwarder contract.\n *\n * @param borrower The address of the borrower for whom the commitment is being accepted.\n * @param principalToken The token in which the loan is being accepted.\n * @param _commitmentArgs The arguments necessary for accepting the commitment.\n *\n * @return bidId_ Identifier of the accepted loan.\n * @return acceptCommitmentAmount_ The amount received from accepting the commitment.\n */\n function _acceptCommitment(\n address lenderCommitmentForwarder,\n address borrower,\n address principalToken,\n AcceptCommitmentArgs memory _commitmentArgs\n )\n internal\n virtual\n returns (uint256 bidId_, uint256 acceptCommitmentAmount_)\n {\n uint256 fundsBeforeAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n\n\n\n if (_commitmentArgs.smartCommitmentAddress != address(0)) {\n\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ISmartCommitmentForwarder\n .acceptSmartCommitmentWithRecipient\n .selector,\n _commitmentArgs.smartCommitmentAddress,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n\n }else { \n\n bool usingMerkleProof = _commitmentArgs.merkleProof.length > 0;\n\n if (usingMerkleProof) {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipientAndProof\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration,\n _commitmentArgs.merkleProof\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n } else {\n bytes memory responseData = address(lenderCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _commitmentArgs.commitmentId,\n _commitmentArgs.principalAmount,\n _commitmentArgs.collateralAmount,\n _commitmentArgs.collateralTokenId,\n _commitmentArgs.collateralTokenAddress,\n address(this),\n _commitmentArgs.interestRate,\n _commitmentArgs.loanDuration\n ),\n borrower //cant be msg.sender because of the flash flow\n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n }\n\n }\n\n uint256 fundsAfterAcceptCommitment = IERC20Upgradeable(principalToken)\n .balanceOf(address(this));\n acceptCommitmentAmount_ =\n fundsAfterAcceptCommitment -\n fundsBeforeAcceptCommitment;\n }\n\n function ADDRESSES_PROVIDER() public view returns (IPoolAddressesProvider) {\n return IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\n }\n\n function POOL() public view returns (IPool) {\n return IPool(ADDRESSES_PROVIDER().getPool());\n }\n\n /**\n * @notice Calculates the amount for loan rollover, determining if the borrower owes or receives funds.\n * @param _loanId The ID of the loan to calculate the rollover amount for.\n * @param _commitmentArgs Arguments for the commitment.\n * @param _timestamp The timestamp for when the calculation is executed.\n \n */\n function calculateRolloverAmount(\n address _lenderCommitmentForwarder,\n uint256 _loanId,\n AcceptCommitmentArgs calldata _commitmentArgs,\n uint256 _rewardAmount, \n uint16 _flashloanPremiumPct,\n uint256 _timestamp\n ) external view returns (uint256 _flashAmount, int256 _borrowerAmount) {\n Payment memory repayAmountOwed = TELLER_V2.calculateAmountOwed(\n _loanId,\n _timestamp\n );\n\n uint256 _marketId = _getMarketIdForCommitment(_lenderCommitmentForwarder,\n _commitmentArgs.commitmentId\n );\n uint16 marketFeePct = _getMarketFeePct(_marketId);\n uint16 protocolFeePct = _getProtocolFeePct();\n\n uint256 commitmentPrincipalRequested = _commitmentArgs.principalAmount;\n uint256 amountToMarketplace = commitmentPrincipalRequested.percent(\n marketFeePct\n );\n uint256 amountToProtocol = commitmentPrincipalRequested.percent(\n protocolFeePct\n );\n\n uint256 commitmentPrincipalReceived = commitmentPrincipalRequested -\n amountToMarketplace -\n amountToProtocol;\n\n // by default, we will flash exactly what we need to do relayLoanFull\n uint256 repayFullAmount = repayAmountOwed.principal +\n repayAmountOwed.interest;\n\n _flashAmount = repayFullAmount;\n uint256 _flashLoanFee = _flashAmount.percent(_flashloanPremiumPct);\n\n _borrowerAmount =\n int256(commitmentPrincipalReceived) -\n int256(repayFullAmount) -\n int256(_flashLoanFee) -\n int256(_rewardAmount);\n }\n\n /**\n * @notice Retrieves the market ID associated with a given commitment.\n * @param _commitmentId The ID of the commitment for which to fetch the market ID.\n * @return The ID of the market associated with the provided commitment.\n */\n function _getMarketIdForCommitment(address _lenderCommitmentForwarder, uint256 _commitmentId)\n internal\n view\n returns (uint256)\n {\n return ILenderCommitmentForwarder(_lenderCommitmentForwarder).getCommitmentMarketId(_commitmentId);\n }\n\n /**\n * @notice Fetches the marketplace fee percentage for a given market ID.\n * @param _marketId The ID of the market for which to fetch the fee percentage.\n * @return The marketplace fee percentage for the provided market ID.\n */\n function _getMarketFeePct(uint256 _marketId)\n internal\n view\n returns (uint16)\n {\n address _marketRegistryAddress = ITellerV2Storage(address(TELLER_V2))\n .marketRegistry();\n\n return\n IMarketRegistry(_marketRegistryAddress).getMarketplaceFee(\n _marketId\n );\n }\n\n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoan.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n \nimport \"./FlashRolloverLoan_G5.sol\";\n\ncontract FlashRolloverLoan is FlashRolloverLoan_G5 {\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n )\n FlashRolloverLoan_G5(\n _tellerV2,\n _poolAddressesProvider\n )\n {}\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/FlashRolloverLoanWidget.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n \nimport \"./FlashRolloverLoan_G6.sol\";\n\ncontract FlashRolloverLoanWidget is FlashRolloverLoan_G6 {\n constructor(\n address _tellerV2,\n address _poolAddressesProvider\n )\n FlashRolloverLoan_G6(\n _tellerV2,\n _poolAddressesProvider\n )\n {}\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Factory.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\"; \n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../../../interfaces/ITellerV2.sol\";\nimport \"../../../interfaces/IProtocolFee.sol\";\nimport \"../../../interfaces/ITellerV2Storage.sol\";\nimport \"../../../libraries/NumbersLib.sol\";\n\nimport {IUniswapPricingLibrary} from \"../../../interfaces/IUniswapPricingLibrary.sol\";\n\nimport \"@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol\";\n \nimport { ILenderCommitmentGroup } from \"../../../interfaces/ILenderCommitmentGroup.sol\";\n\ncontract LenderCommitmentGroupFactory is OwnableUpgradeable {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n \n //this is the beacon proxy\n address public lenderGroupBeacon;\n\n\n mapping(address => uint256) public deployedLenderGroupContracts;\n\n event DeployedLenderGroupContract(address indexed groupContract);\n\n \n\n function initialize(address _lenderGroupBeacon )\n external\n initializer\n {\n lenderGroupBeacon = _lenderGroupBeacon; \n __Ownable_init_unchained();\n }\n\n\n /*\n This should deploy a new lender commitment group pool contract.\n It will use create commitment args in order to define the pool contracts parameters such as its primary principal token. \n Shares will be distributed at a 1:1 ratio of the primary principal token so if 1e18 raw WETH are deposited, the depositor gets 1e18 shares for the group pool.\n */\n function deployLenderCommitmentGroupPool(\n uint256 _initialPrincipalAmount,\n ILenderCommitmentGroup.CommitmentGroupConfig calldata _commitmentGroupConfig,\n IUniswapPricingLibrary.PoolRouteConfig[] calldata _poolOracleRoutes\n ) external returns (address newGroupContract_) {\n \n\n \n BeaconProxy newGroupContract_ = new BeaconProxy(\n lenderGroupBeacon,\n abi.encodeWithSelector(\n ILenderCommitmentGroup.initialize.selector, //this initializes \n _commitmentGroupConfig,\n _poolOracleRoutes\n\n )\n );\n\n deployedLenderGroupContracts[address(newGroupContract_)] = block.number; //consider changing this ?\n emit DeployedLenderGroupContract(address(newGroupContract_));\n\n\n\n //it is not absolutely necessary to have this call here but it allows the user to potentially save a tx step so it is nice to have .\n if (_initialPrincipalAmount > 0) {\n //should pull in the creators initial committed principal tokens .\n\n //send the initial principal tokens to _newgroupcontract here !\n // so it will have them for addPrincipalToCommitmentGroup which will pull them from here\n\n _addPrincipalToCommitmentGroup(\n address(newGroupContract_),\n _initialPrincipalAmount,\n _commitmentGroupConfig.principalTokenAddress \n \n );\n\n \n } \n\n\n //transfer ownership to msg.sender \n OwnableUpgradeable(address(newGroupContract_))\n .transferOwnership(msg.sender);\n }\n\n\n\n function _addPrincipalToCommitmentGroup(\n address _newGroupContract,\n uint256 _initialPrincipalAmount,\n address _principalTokenAddress\n ) internal {\n\n\n IERC20(_principalTokenAddress).transferFrom(\n msg.sender,\n address(this),\n _initialPrincipalAmount\n );\n IERC20(_principalTokenAddress).approve(\n _newGroupContract,\n _initialPrincipalAmount\n );\n\n address sharesRecipient = msg.sender; \n\n uint256 sharesAmount_ = ILenderCommitmentGroup(address(_newGroupContract))\n .addPrincipalToCommitmentGroup(\n _initialPrincipalAmount,\n sharesRecipient,\n 0 //_minShares\n );\n\n\n }\n\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n\n// Interfaces\nimport \"../../../interfaces/ITellerV2Context.sol\";\nimport \"../../../interfaces/IProtocolFee.sol\";\n \nimport \"../../../interfaces/ITellerV2.sol\";\n\n//import \"../../../interfaces/IFlashRolloverLoan.sol\";\nimport \"../../../libraries/NumbersLib.sol\";\n\nimport \"../../../interfaces/uniswap/IUniswapV3Pool.sol\";\n\nimport \"../../../interfaces/uniswap/IUniswapV3Factory.sol\";\nimport \"../../../interfaces/ISmartCommitmentForwarder.sol\";\n\nimport \"../../../libraries/uniswap/TickMath.sol\";\nimport \"../../../libraries/uniswap/FixedPoint96.sol\";\nimport \"../../../libraries/uniswap/FullMath.sol\";\n\nimport {LenderCommitmentGroupShares} from \"./LenderCommitmentGroupShares.sol\";\n\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\nimport { CommitmentCollateralType, ISmartCommitment } from \"../../../interfaces/ISmartCommitment.sol\";\nimport { ILoanRepaymentListener } from \"../../../interfaces/ILoanRepaymentListener.sol\";\n\nimport { ILoanRepaymentCallbacks } from \"../../../interfaces/ILoanRepaymentCallbacks.sol\";\n\nimport { IEscrowVault } from \"../../../interfaces/IEscrowVault.sol\";\n\nimport { IPausableTimestamp } from \"../../../interfaces/IPausableTimestamp.sol\";\nimport { ILenderCommitmentGroup } from \"../../../interfaces/ILenderCommitmentGroup.sol\";\nimport { Payment } from \"../../../TellerV2Storage.sol\";\n\nimport {IUniswapPricingLibrary} from \"../../../interfaces/IUniswapPricingLibrary.sol\";\nimport {UniswapPricingLibrary} from \"../../../libraries/UniswapPricingLibrary.sol\";\n\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n/*\n \n\n Each LenderCommitmentGroup SmartContract acts as its own Loan Commitment (for the SmartCommitmentForwarder) and acts as its own Lender in the Teller Protocol.\n\n Lender Users can deposit principal tokens in this contract and this will give them Share Tokens (LP tokens) representing their ownership in the liquidity pool of this contract.\n\n Borrower Users can borrow principal token funds from this contract (via the SCF contract) by providing collateral tokens in the proper amount as specified by the rules of this smart contract.\n These collateral tokens are then owned by this smart contract and are returned to the borrower via the Teller Protocol rules to the borrower if and only if the borrower repays principal and interest of the loan they took.\n\n If the borrower defaults on a loan, for 24 hours a liquidation auction is automatically conducted by this smart contract in order to incentivize a liquidator to take the collateral tokens in exchange for principal tokens.\n\n \n \n\n*/\n\ncontract LenderCommitmentGroup_Smart is\n ILenderCommitmentGroup,\n ISmartCommitment,\n ILoanRepaymentListener,\n IPausableTimestamp,\n Initializable,\n OwnableUpgradeable,\n PausableUpgradeable\n{\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n uint256 public immutable STANDARD_EXPANSION_FACTOR = 1e18;\n\n uint256 public immutable MIN_TWAP_INTERVAL = 3;\n\n uint256 public immutable UNISWAP_EXPANSION_FACTOR = 2**96;\n\n uint256 public immutable EXCHANGE_RATE_EXPANSION_FACTOR = 1e36; \n\n using SafeERC20 for IERC20;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable TELLER_V2;\n address public immutable SMART_COMMITMENT_FORWARDER;\n address public immutable UNISWAP_V3_FACTORY;\n address private UNISWAP_V3_POOL; //deprecated\n \n LenderCommitmentGroupShares public poolSharesToken;\n\n IERC20 public principalToken;\n IERC20 public collateralToken;\n uint24 private _uniswapPoolFee; //deprecated\n\n uint256 marketId;\n\n \n uint256 public totalPrincipalTokensCommitted; \n uint256 public totalPrincipalTokensWithdrawn;\n\n uint256 public totalPrincipalTokensLended;\n uint256 public totalPrincipalTokensRepaid; //subtract this and the above to find total principal tokens outstanding for loans\n\n \n \n uint256 public totalInterestCollected;\n\n uint16 public liquidityThresholdPercent; //5000 is 50 pct // enforce max of 10000\n uint16 public collateralRatio; //the overcollateralization ratio, typically 80 pct\n\n uint32 private _twapInterval; //deprecated\n uint32 public maxLoanDuration;\n uint16 public interestRateLowerBound;\n uint16 public interestRateUpperBound;\n\n\n\n\n mapping(address => uint256) public poolSharesPreparedToWithdrawForLender;\n mapping(address => uint256) public poolSharesPreparedTimestamp;\n uint256 immutable public DEFAULT_WITHDRAWL_DELAY_TIME_SECONDS = 300;\n uint256 immutable public MAX_WITHDRAWL_DELAY_TIME = 86400;\n\n //mapping(address => uint256) public principalTokensCommittedByLender;\n mapping(uint256 => bool) public activeBids;\n\n //this excludes interest\n // maybe it is possible to get rid of this storage slot and calculate it from totalPrincipalTokensRepaid, totalPrincipalTokensLended\n int256 tokenDifferenceFromLiquidations;\n\n bool public firstDepositMade;\n uint256 public withdrawlDelayTimeSeconds; \n\n IUniswapPricingLibrary.PoolRouteConfig[] public poolOracleRoutes ;\n\n //configured by the owner. If 0 , not used. \n uint256 public maxPrincipalPerCollateralAmount; \n\n\n uint256 public lastUnpausedAt;\n \n\n event PoolInitialized(\n address indexed principalTokenAddress,\n address indexed collateralTokenAddress,\n uint256 marketId,\n uint32 maxLoanDuration,\n uint16 interestRateLowerBound,\n uint16 interestRateUpperBound,\n uint16 liquidityThresholdPercent,\n uint16 loanToValuePercent,\n // uint24 uniswapPoolFee,\n // uint32 twapInterval,\n address poolSharesToken\n );\n\n event LenderAddedPrincipal(\n address indexed lender,\n uint256 amount,\n uint256 sharesAmount,\n address indexed sharesRecipient\n );\n\n event BorrowerAcceptedFunds(\n address indexed borrower,\n uint256 indexed bidId,\n uint256 principalAmount,\n uint256 collateralAmount,\n uint32 loanDuration,\n uint16 interestRate\n );\n\n event EarningsWithdrawn(\n address indexed lender,\n uint256 amountPoolSharesTokens,\n uint256 principalTokensWithdrawn,\n address indexed recipient\n );\n\n\n event DefaultedLoanLiquidated(\n uint256 indexed bidId,\n address indexed liquidator,\n uint256 amountDue, \n int256 tokenAmountDifference \n );\n\n\n event LoanRepaid(\n uint256 indexed bidId,\n address indexed repayer,\n uint256 principalAmount,\n uint256 interestAmount,\n uint256 totalPrincipalRepaid,\n uint256 totalInterestCollected\n );\n\n event PoolSharesPrepared(\n address lender,\n uint256 sharesAmount,\n uint256 preparedAt\n\n );\n\n\n modifier onlySmartCommitmentForwarder() {\n require(\n msg.sender == address(SMART_COMMITMENT_FORWARDER),\n \"Can only be called by Smart Commitment Forwarder\"\n );\n _;\n }\n\n modifier onlyTellerV2() {\n require(\n msg.sender == address(TELLER_V2),\n \"Can only be called by TellerV2\"\n );\n _;\n }\n\n\n modifier onlyProtocolOwner() {\n require(\n msg.sender == Ownable(address(TELLER_V2)).owner(),\n \"Can only be called by TellerV2\"\n );\n _;\n }\n\n modifier bidIsActiveForGroup(uint256 _bidId) {\n require(activeBids[_bidId] == true, \"Bid is not active for group\");\n\n _;\n }\n\n modifier whenForwarderNotPaused() {\n require( PausableUpgradeable(address(SMART_COMMITMENT_FORWARDER)).paused() == false , \"Smart Commitment Forwarder is paused\");\n _;\n }\n\n\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2,\n address _smartCommitmentForwarder,\n address _uniswapV3Factory\n ) {\n TELLER_V2 = _tellerV2;\n SMART_COMMITMENT_FORWARDER = _smartCommitmentForwarder;\n UNISWAP_V3_FACTORY = _uniswapV3Factory;\n \n }\n\n /*\n\n\n \n */\n function initialize(\n CommitmentGroupConfig calldata _commitmentGroupConfig,\n IUniswapPricingLibrary.PoolRouteConfig[] calldata _poolOracleRoutes\n ) external initializer returns (address poolSharesToken_) {\n \n __Ownable_init();\n __Pausable_init();\n\n principalToken = IERC20(_commitmentGroupConfig.principalTokenAddress);\n collateralToken = IERC20(_commitmentGroupConfig.collateralTokenAddress);\n /*uniswapPoolFee = _commitmentGroupConfig.uniswapPoolFee;\n\n UNISWAP_V3_POOL = IUniswapV3Factory(UNISWAP_V3_FACTORY).getPool(\n _commitmentGroupConfig.principalTokenAddress,\n _commitmentGroupConfig.collateralTokenAddress,\n _commitmentGroupConfig.uniswapPoolFee\n );*/\n\n //require(_commitmentGroupConfig.twapInterval >= MIN_TWAP_INTERVAL, \"Invalid TWAP Interval\");\n // require(UNISWAP_V3_POOL != address(0), \"Invalid uniswap pool address\");\n\n marketId = _commitmentGroupConfig.marketId;\n\n withdrawlDelayTimeSeconds = DEFAULT_WITHDRAWL_DELAY_TIME_SECONDS;\n\n //in order for this to succeed, first, that SmartCommitmentForwarder needs to be THE trusted forwarder for the market\n\n \n ITellerV2Context(TELLER_V2).approveMarketForwarder(\n _commitmentGroupConfig.marketId,\n SMART_COMMITMENT_FORWARDER\n );\n\n maxLoanDuration = _commitmentGroupConfig.maxLoanDuration;\n interestRateLowerBound = _commitmentGroupConfig.interestRateLowerBound;\n interestRateUpperBound = _commitmentGroupConfig.interestRateUpperBound;\n\n\n \n \n require(interestRateLowerBound <= interestRateUpperBound, \"invalid _interestRateLowerBound\");\n\n \n liquidityThresholdPercent = _commitmentGroupConfig.liquidityThresholdPercent;\n collateralRatio = _commitmentGroupConfig.collateralRatio;\n //twapInterval = _commitmentGroupConfig.twapInterval;\n\n require( liquidityThresholdPercent <= 10000, \"invalid _liquidityThresholdPercent\"); \n\n \n\n for (uint256 i = 0; i < _poolOracleRoutes.length; i++) {\n poolOracleRoutes.push(_poolOracleRoutes[i]);\n }\n\n\n require(poolOracleRoutes.length >= 1 && poolOracleRoutes.length <= 2, \"invalid pool routes length\");\n \n poolSharesToken_ = _deployPoolSharesToken();\n\n\n emit PoolInitialized(\n _commitmentGroupConfig.principalTokenAddress,\n _commitmentGroupConfig.collateralTokenAddress,\n _commitmentGroupConfig.marketId,\n _commitmentGroupConfig.maxLoanDuration,\n _commitmentGroupConfig.interestRateLowerBound,\n _commitmentGroupConfig.interestRateUpperBound,\n _commitmentGroupConfig.liquidityThresholdPercent,\n _commitmentGroupConfig.collateralRatio,\n //_commitmentGroupConfig.uniswapPoolFee,\n //_commitmentGroupConfig.twapInterval,\n poolSharesToken_\n );\n }\n\n\n\n function setWithdrawlDelayTime(uint256 _seconds) \n external \n onlyProtocolOwner {\n\n require( _seconds < MAX_WITHDRAWL_DELAY_TIME );\n\n withdrawlDelayTimeSeconds = _seconds;\n }\n\n\n\n function setMaxPrincipalPerCollateralAmount(uint256 _maxPrincipalPerCollateralAmount) \n external \n onlyOwner {\n\n maxPrincipalPerCollateralAmount = _maxPrincipalPerCollateralAmount;\n }\n\n function _deployPoolSharesToken()\n internal\n onlyInitializing\n returns (address poolSharesToken_)\n {\n \n require(\n address(poolSharesToken) == address(0),\n \"Pool shares already deployed\"\n );\n \n poolSharesToken = new LenderCommitmentGroupShares(\n \"LenderGroupShares\",\n \"SHR\",\n 18 \n );\n\n return address(poolSharesToken);\n } \n\n\n /**\n * @notice This determines the number of shares you get for depositing principal tokens and the number of principal tokens you receive for burning shares\n * @return rate_ The current exchange rate, scaled by the EXCHANGE_RATE_FACTOR.\n */\n\n function sharesExchangeRate() public view virtual returns (uint256 rate_) {\n \n\n uint256 poolTotalEstimatedValue = getPoolTotalEstimatedValue();\n\n if (poolSharesToken.totalSupply() == 0) {\n return EXCHANGE_RATE_EXPANSION_FACTOR; // 1 to 1 for first swap\n }\n\n rate_ =\n MathUpgradeable.mulDiv(poolTotalEstimatedValue , \n EXCHANGE_RATE_EXPANSION_FACTOR ,\n poolSharesToken.totalSupply() );\n }\n\n function sharesExchangeRateInverse()\n public\n view\n virtual\n returns (uint256 rate_)\n {\n return\n (EXCHANGE_RATE_EXPANSION_FACTOR * EXCHANGE_RATE_EXPANSION_FACTOR) /\n sharesExchangeRate();\n }\n\n function getPoolTotalEstimatedValue()\n public\n view\n returns (uint256 poolTotalEstimatedValue_)\n {\n \n int256 poolTotalEstimatedValueSigned = int256(totalPrincipalTokensCommitted) \n + int256(totalInterestCollected) + int256(tokenDifferenceFromLiquidations) \n - int256(totalPrincipalTokensWithdrawn);\n\n //if the poolTotalEstimatedValue_ is less than 0, we treat it as 0. \n poolTotalEstimatedValue_ = poolTotalEstimatedValueSigned > int256(0)\n ? uint256(poolTotalEstimatedValueSigned)\n : 0;\n }\n\n /*\n must be initialized for this to work ! \n */\n function addPrincipalToCommitmentGroup(\n uint256 _amount,\n address _sharesRecipient,\n uint256 _minSharesAmountOut\n ) external whenForwarderNotPaused whenNotPaused returns (uint256 sharesAmount_) {\n //transfers the primary principal token from msg.sender into this contract escrow\n\n \n\n \n \n uint256 principalTokenBalanceBefore = principalToken.balanceOf(address(this));\n\n principalToken.safeTransferFrom(msg.sender, address(this), _amount);\n \n uint256 principalTokenBalanceAfter = principalToken.balanceOf(address(this));\n \n require( principalTokenBalanceAfter == principalTokenBalanceBefore + _amount, \"Token balance was not added properly\" );\n\n\n\n sharesAmount_ = _valueOfUnderlying(_amount, sharesExchangeRate());\n\n \n\n totalPrincipalTokensCommitted += _amount;\n \n\n //mint shares equal to _amount and give them to the shares recipient !!!\n poolSharesToken.mint(_sharesRecipient, sharesAmount_);\n \n \n\n // prepare current balance \n uint256 sharesBalance = poolSharesToken.balanceOf(address(_sharesRecipient));\n _prepareSharesForWithdraw(_sharesRecipient,sharesBalance); \n\n\n emit LenderAddedPrincipal( \n\n msg.sender,\n _amount,\n sharesAmount_,\n _sharesRecipient\n\n );\n\n require( sharesAmount_ >= _minSharesAmountOut, \"Invalid: Min Shares AmountOut\" );\n \n if(!firstDepositMade){\n require(msg.sender == owner(), \"Owner must initialize the pool with a deposit first.\");\n require( sharesAmount_>= 1e6, \"Initial shares amount must be atleast 1e6\" );\n\n firstDepositMade = true;\n }\n }\n\n function _valueOfUnderlying(uint256 amount, uint256 rate)\n internal\n pure\n returns (uint256 value_)\n {\n if (rate == 0) {\n return 0;\n }\n\n value_ = MathUpgradeable.mulDiv(amount , EXCHANGE_RATE_EXPANSION_FACTOR , rate ) ;\n }\n\n function acceptFundsForAcceptBid(\n address _borrower,\n uint256 _bidId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n address _collateralTokenAddress,\n uint256 _collateralTokenId, \n uint32 _loanDuration,\n uint16 _interestRate\n ) external onlySmartCommitmentForwarder whenForwarderNotPaused whenNotPaused {\n \n require(\n _collateralTokenAddress == address(collateralToken),\n \"Mismatching collateral token\"\n );\n //the interest rate must be at least as high has the commitment demands. The borrower can use a higher interest rate although that would not be beneficial to the borrower.\n require(_interestRate >= getMinInterestRate(_principalAmount), \"Invalid interest rate\");\n //the loan duration must be less than the commitment max loan duration. The lender who made the commitment expects the money to be returned before this window.\n require(_loanDuration <= maxLoanDuration, \"Invalid loan max duration\");\n\n require(\n getPrincipalAmountAvailableToBorrow() >= _principalAmount,\n \"Invalid loan max principal\"\n );\n \n \n uint256 requiredCollateral = calculateCollateralRequiredToBorrowPrincipal(\n _principalAmount\n );\n\n\n\n require( \n _collateralAmount >=\n requiredCollateral,\n \"Insufficient Borrower Collateral\"\n );\n \n principalToken.approve(address(TELLER_V2), _principalAmount);\n\n //do not have to spoof/forward as this contract is the lender !\n _acceptBidWithRepaymentListener(_bidId);\n\n totalPrincipalTokensLended += _principalAmount;\n\n activeBids[_bidId] = true; //bool for now\n \n\n emit BorrowerAcceptedFunds( \n _borrower,\n _bidId,\n _principalAmount,\n _collateralAmount, \n _loanDuration,\n _interestRate \n );\n }\n\n function _acceptBidWithRepaymentListener(uint256 _bidId) internal {\n ITellerV2(TELLER_V2).lenderAcceptBid(_bidId); //this gives out the funds to the borrower\n\n ILoanRepaymentCallbacks(TELLER_V2).setRepaymentListenerForBid(\n _bidId,\n address(this)\n );\n\n \n }\n\n function prepareSharesForWithdraw(\n uint256 _amountPoolSharesTokens \n ) external whenForwarderNotPaused whenNotPaused returns (bool) {\n \n return _prepareSharesForWithdraw(msg.sender, _amountPoolSharesTokens); \n }\n\n function _prepareSharesForWithdraw(\n address _recipient,\n uint256 _amountPoolSharesTokens \n ) internal returns (bool) {\n \n require( poolSharesToken.balanceOf(_recipient) >= _amountPoolSharesTokens );\n\n poolSharesPreparedToWithdrawForLender[_recipient] = _amountPoolSharesTokens; \n poolSharesPreparedTimestamp[_recipient] = block.timestamp; \n\n\n emit PoolSharesPrepared( \n\n _recipient,\n _amountPoolSharesTokens,\n block.timestamp\n\n );\n\n return true; \n }\n\n\n /*\n \n */\n function burnSharesToWithdrawEarnings(\n uint256 _amountPoolSharesTokens,\n address _recipient,\n uint256 _minAmountOut\n ) external whenForwarderNotPaused whenNotPaused returns (uint256) {\n \n require(poolSharesPreparedToWithdrawForLender[msg.sender] >= _amountPoolSharesTokens,\"Shares not prepared for withdraw\");\n require(poolSharesPreparedTimestamp[msg.sender] <= block.timestamp - withdrawlDelayTimeSeconds,\"Shares not prepared for withdraw\");\n \n \n poolSharesPreparedToWithdrawForLender[msg.sender] = 0;\n poolSharesPreparedTimestamp[msg.sender] = block.timestamp;\n \n \n //this should compute BEFORE shares burn \n uint256 principalTokenValueToWithdraw = _valueOfUnderlying(\n _amountPoolSharesTokens,\n sharesExchangeRateInverse()\n );\n\n poolSharesToken.burn(msg.sender, _amountPoolSharesTokens);\n\n totalPrincipalTokensWithdrawn += principalTokenValueToWithdraw;\n\n principalToken.safeTransfer(_recipient, principalTokenValueToWithdraw);\n\n\n emit EarningsWithdrawn(\n msg.sender,\n _amountPoolSharesTokens,\n principalTokenValueToWithdraw,\n _recipient\n );\n \n require( principalTokenValueToWithdraw >= _minAmountOut ,\"Invalid: Min Amount Out\");\n\n return principalTokenValueToWithdraw;\n }\n\n /*\n\n\n */\n\n function liquidateDefaultedLoanWithIncentive(\n uint256 _bidId,\n int256 _tokenAmountDifference\n ) public whenForwarderNotPaused whenNotPaused bidIsActiveForGroup(_bidId) {\n \n //use original principal amount as amountDue\n\n uint256 amountDue = _getAmountOwedForBid(_bidId);\n\n \n\n uint256 loanDefaultedTimeStamp = ITellerV2(TELLER_V2)\n .getLoanDefaultTimestamp(_bidId);\n\n uint256 loanDefaultedOrUnpausedAtTimeStamp = Math.max(\n loanDefaultedTimeStamp,\n getLastUnpausedAt()\n );\n\n int256 minAmountDifference = getMinimumAmountDifferenceToCloseDefaultedLoan(\n amountDue,\n loanDefaultedOrUnpausedAtTimeStamp\n );\n\n require(\n _tokenAmountDifference >= minAmountDifference,\n \"Insufficient tokenAmountDifference\"\n );\n\n\n if (minAmountDifference > 0) {\n //this is used when the collateral value is higher than the principal (rare)\n //the loan will be completely made whole and our contract gets extra funds too\n uint256 tokensToTakeFromSender = abs(minAmountDifference);\n\n \n \n \n uint256 liquidationProtocolFee = Math.mulDiv( \n tokensToTakeFromSender , \n ISmartCommitmentForwarder(SMART_COMMITMENT_FORWARDER)\n .getLiquidationProtocolFeePercent(),\n 10000) ;\n \n\n IERC20(principalToken).safeTransferFrom(\n msg.sender,\n address(this),\n amountDue + tokensToTakeFromSender - liquidationProtocolFee\n ); \n \n address protocolOwner = Ownable(address(TELLER_V2)).owner();\n\n IERC20(principalToken).safeTransferFrom(\n msg.sender,\n address(protocolOwner),\n liquidationProtocolFee\n );\n\n totalPrincipalTokensRepaid += amountDue;\n tokenDifferenceFromLiquidations += int256(tokensToTakeFromSender - liquidationProtocolFee );\n\n\n } else {\n \n \n uint256 tokensToGiveToSender = abs(minAmountDifference);\n\n \n IERC20(principalToken).safeTransferFrom(\n msg.sender,\n address(this),\n amountDue - tokensToGiveToSender \n );\n\n totalPrincipalTokensRepaid += amountDue;\n\n //this will make tokenDifference go more negative\n tokenDifferenceFromLiquidations -= int256(tokensToGiveToSender);\n\n \n }\n\n \n\n //this will give collateral to the caller\n ITellerV2(TELLER_V2).lenderCloseLoanWithRecipient(_bidId, msg.sender);\n \n \n emit DefaultedLoanLiquidated(\n _bidId,\n msg.sender,\n amountDue, \n _tokenAmountDifference\n );\n }\n\n\n function getLastUnpausedAt() \n public view \n returns (uint256) {\n\n\n return Math.max(\n lastUnpausedAt,\n IPausableTimestamp(SMART_COMMITMENT_FORWARDER).getLastUnpausedAt() //this counts tellerV2 pausing\n )\n ;\n \n\n }\n\n\n function setLastUnpausedAt() internal {\n lastUnpausedAt = block.timestamp;\n }\n\n \n\n function _getAmountOwedForBid(uint256 _bidId )\n internal\n view\n virtual\n returns (uint256 amountDue)\n {\n (,,,, amountDue, , , )\n = ITellerV2(TELLER_V2).getLoanSummary(_bidId);\n\n \n }\n\n\n function getTokenDifferenceFromLiquidations() public view returns (int256){\n\n return tokenDifferenceFromLiquidations;\n\n }\n \n\n /*\n This function will calculate the incentive amount (using a uniswap bonus plus a timer)\n of principal tokens that will be given to incentivize liquidating a loan \n \n */\n function getMinimumAmountDifferenceToCloseDefaultedLoan(\n uint256 _amountOwed,\n uint256 _loanDefaultedTimestamp\n ) public view virtual returns (int256 amountDifference_) {\n require(\n _loanDefaultedTimestamp > 0,\n \"Loan defaulted timestamp must be greater than zero\"\n );\n require(\n block.timestamp > _loanDefaultedTimestamp,\n \"Loan defaulted timestamp must be in the past\"\n );\n\n uint256 secondsSinceDefaulted = block.timestamp -\n _loanDefaultedTimestamp;\n\n //this starts at 764% and falls to -100% \n int256 incentiveMultiplier = int256(86400 - 10000) -\n int256(secondsSinceDefaulted);\n\n if (incentiveMultiplier < -10000) {\n incentiveMultiplier = -10000;\n }\n\n amountDifference_ =\n (int256(_amountOwed) * incentiveMultiplier) /\n int256(10000);\n }\n\n function abs(int x) private pure returns (uint) {\n return x >= 0 ? uint(x) : uint(-x);\n }\n\n\n function calculateCollateralRequiredToBorrowPrincipal( \n uint256 _principalAmount\n ) public\n view\n virtual\n returns (uint256) {\n\n uint256 baseAmount = calculateCollateralTokensAmountEquivalentToPrincipalTokens(\n _principalAmount\n ); \n\n //this is an amount of collateral\n return baseAmount.percent(collateralRatio);\n }\n\n\n //this is expanded by 10e18\n //this logic is very similar to that used in LCFA \n function calculateCollateralTokensAmountEquivalentToPrincipalTokens(\n uint256 principalAmount \n ) public view virtual returns (uint256 collateralTokensAmountToMatchValue) {\n \n uint256 pairPriceWithTwapFromOracle = UniswapPricingLibrary\n .getUniswapPriceRatioForPoolRoutes(poolOracleRoutes);\n \n \n uint256 principalPerCollateralAmount = maxPrincipalPerCollateralAmount == 0 \n ? pairPriceWithTwapFromOracle \n : Math.min(\n pairPriceWithTwapFromOracle,\n maxPrincipalPerCollateralAmount //this is expanded by uniswap exp factor \n ) ;\n\n\n return\n getRequiredCollateral(\n principalAmount,\n principalPerCollateralAmount \n );\n }\n\n\n\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount \n \n ) public view virtual returns (uint256) {\n \n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n STANDARD_EXPANSION_FACTOR,\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n ); \n }\n \n\n /*\n This callback occurs when a TellerV2 repayment happens or when a TellerV2 liquidate happens \n\n lenderCloseLoan does not trigger a repayLoanCallback \n */\n function repayLoanCallback(\n uint256 _bidId,\n address repayer,\n uint256 principalAmount,\n uint256 interestAmount\n ) external onlyTellerV2 whenForwarderNotPaused whenNotPaused {\n //can use principal amt to increment amt paid back!! nice for math .\n totalPrincipalTokensRepaid += principalAmount;\n totalInterestCollected += interestAmount;\n\n emit LoanRepaid(\n _bidId,\n repayer,\n principalAmount,\n interestAmount,\n totalPrincipalTokensRepaid,\n totalInterestCollected\n );\n }\n\n\n /*\n If principaltokens get stuck in the escrow vault for any reason, anyone may\n call this function to move them from that vault in to this contract \n */\n function withdrawFromEscrowVault ( uint256 _amount ) public whenForwarderNotPaused whenNotPaused {\n\n\n address _escrowVault = ITellerV2(TELLER_V2).getEscrowVault();\n\n IEscrowVault(_escrowVault).withdraw(address(principalToken), _amount );\n\n }\n \n \n function getTotalPrincipalTokensOutstandingInActiveLoans()\n public\n view\n returns (uint256)\n {\n return totalPrincipalTokensLended - totalPrincipalTokensRepaid;\n }\n\n\n\n\n function getCollateralTokenAddress() external view returns (address) {\n return address(collateralToken);\n }\n\n function getCollateralTokenId() external view returns (uint256) {\n return 0;\n }\n\n function getCollateralTokenType()\n external\n view\n returns (CommitmentCollateralType)\n {\n return CommitmentCollateralType.ERC20;\n }\n\n //this was a redundant function \n /* function getRequiredCollateral(uint256 _principalAmount)\n public\n view\n returns (uint256 requiredCollateral_)\n {\n requiredCollateral_ = getCollateralRequiredForPrincipalAmount(\n _principalAmount\n );\n }*/\n\n function getMarketId() external view returns (uint256) {\n return marketId;\n }\n\n function getMaxLoanDuration() external view returns (uint32) {\n return maxLoanDuration;\n }\n\n\n function getPoolUtilizationRatio(uint256 activeLoansAmountDelta ) public view returns (uint16) {\n\n if (getPoolTotalEstimatedValue() == 0) {\n return 0;\n }\n\n return uint16( Math.min( \n MathUpgradeable.mulDiv( \n (getTotalPrincipalTokensOutstandingInActiveLoans() + activeLoansAmountDelta), \n 10000 ,\n getPoolTotalEstimatedValue() ) , \n 10000 ));\n\n }\n\n function getMinInterestRate(uint256 amountDelta) public view returns (uint16) {\n return interestRateLowerBound + \n uint16( uint256(interestRateUpperBound-interestRateLowerBound)\n .percent(getPoolUtilizationRatio(amountDelta )\n \n ) );\n } \n \n\n function getPrincipalTokenAddress() external view returns (address) {\n return address(principalToken);\n }\n\n \n\n function getPrincipalAmountAvailableToBorrow()\n public\n view\n returns (uint256)\n { \n\n return ( uint256( getPoolTotalEstimatedValue() )).percent(liquidityThresholdPercent) -\n getTotalPrincipalTokensOutstandingInActiveLoans() ;\n \n }\n\n /**\n * @notice Lets the DAO/owner of the protocol implement an emergency stop mechanism.\n */\n function pauseLendingPool() public virtual onlyOwner whenNotPaused {\n _pause();\n }\n\n /**\n * @notice Lets the DAO/owner of the protocol undo a previously implemented emergency stop.\n */\n function unpauseLendingPool() public virtual onlyOwner whenPaused {\n setLastUnpausedAt();\n _unpause();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroupShares.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\ncontract LenderCommitmentGroupShares is ERC20, Ownable {\n uint8 private immutable DECIMALS;\n\n constructor(string memory _name, string memory _symbol, uint8 _decimals)\n ERC20(_name, _symbol)\n Ownable()\n {\n DECIMALS = _decimals;\n }\n\n function mint(address _recipient, uint256 _amount) external onlyOwner {\n _mint(_recipient, _amount);\n }\n\n function burn(address _burner, uint256 _amount) external onlyOwner {\n _burn(_burner, _amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return DECIMALS;\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_G1.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"../TellerV2MarketForwarder_G1.sol\";\n\n// Interfaces\nimport \"../interfaces/ICollateralManager.sol\";\nimport { Collateral, CollateralType } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\n\ncontract LenderCommitmentForwarder_G1 is TellerV2MarketForwarder_G1 {\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n enum CommitmentCollateralType {\n NONE, // no collateral required\n ERC20,\n ERC721,\n ERC1155,\n ERC721_ANY_ID,\n ERC1155_ANY_ID,\n ERC721_MERKLE_PROOF,\n ERC1155_MERKLE_PROOF\n }\n\n /**\n * @notice Details about a lender's capital commitment.\n * @param maxPrincipal Amount of tokens being committed by the lender. Max amount that can be loaned.\n * @param expiration Expiration time in seconds, when the commitment expires.\n * @param maxDuration Length of time, in seconds that the lender's capital can be lent out for.\n * @param minInterestRate Minimum Annual percentage to be applied for loans using the lender's capital.\n * @param collateralTokenAddress The address for the token contract that must be used to provide collateral for loans for this commitment.\n * @param maxPrincipalPerCollateralAmount The amount of principal that can be used for a loan per each unit of collateral, expanded additionally by principal decimals.\n * @param collateralTokenType The type of asset of the collateralTokenAddress (ERC20, ERC721, or ERC1155).\n * @param lender The address of the lender for this commitment.\n * @param marketId The market id for this commitment.\n * @param principalTokenAddress The address for the token contract that will be used to provide principal for loans of this commitment.\n */\n struct Commitment {\n uint256 maxPrincipal;\n uint32 expiration;\n uint32 maxDuration;\n uint16 minInterestRate;\n address collateralTokenAddress;\n uint256 collateralTokenId; //we use this for the MerkleRootHash for type ERC721_MERKLE_PROOF\n uint256 maxPrincipalPerCollateralAmount;\n CommitmentCollateralType collateralTokenType;\n address lender;\n uint256 marketId;\n address principalTokenAddress;\n }\n\n // CommitmentId => commitment\n mapping(uint256 => Commitment) public commitments;\n\n uint256 commitmentCount;\n\n //https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/structs/EnumerableSetUpgradeable.sol\n mapping(uint256 => EnumerableSetUpgradeable.AddressSet)\n internal commitmentBorrowersList;\n\n mapping(uint256 => uint256) public commitmentPrincipalAccepted;\n\n /**\n * @notice This event is emitted when a lender's commitment is created.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event CreatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when a lender's commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event UpdatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when the allowed borrowers for a commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n */\n event UpdatedCommitmentBorrowers(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment has been deleted.\n * @param commitmentId The id of the commitment that was deleted.\n */\n event DeletedCommitment(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment is exercised for a loan.\n * @param commitmentId The id of the commitment that was exercised.\n * @param borrower The address of the borrower.\n * @param tokenAmount The amount of the asset being committed.\n * @param bidId The bid id for the loan from TellerV2.\n */\n event ExercisedCommitment(\n uint256 indexed commitmentId,\n address borrower,\n uint256 tokenAmount,\n uint256 bidId\n );\n\n error InsufficientCommitmentAllocation(\n uint256 allocated,\n uint256 requested\n );\n error InsufficientBorrowerCollateral(uint256 required, uint256 actual);\n\n /** Modifiers **/\n\n modifier commitmentLender(uint256 _commitmentId) {\n require(\n commitments[_commitmentId].lender == _msgSender(),\n \"unauthorized commitment lender\"\n );\n _;\n }\n\n function validateCommitment(Commitment storage _commitment) internal {\n require(\n _commitment.expiration > uint32(block.timestamp),\n \"expired commitment\"\n );\n require(\n _commitment.maxPrincipal > 0,\n \"commitment principal allocation 0\"\n );\n\n if (_commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n require(\n _commitment.maxPrincipalPerCollateralAmount > 0,\n \"commitment collateral ratio 0\"\n );\n\n if (\n _commitment.collateralTokenType ==\n CommitmentCollateralType.ERC20\n ) {\n require(\n _commitment.collateralTokenId == 0,\n \"commitment collateral token id must be 0 for ERC20\"\n );\n }\n }\n }\n\n /** External Functions **/\n\n constructor(address _protocolAddress, address _marketRegistry)\n TellerV2MarketForwarder_G1(_protocolAddress, _marketRegistry)\n {}\n\n /**\n * @notice Creates a loan commitment from a lender for a market.\n * @param _commitment The new commitment data expressed as a struct\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n * @return commitmentId_ returns the commitmentId for the created commitment\n */\n function createCommitment(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList\n ) public returns (uint256 commitmentId_) {\n commitmentId_ = commitmentCount++;\n\n require(\n _commitment.lender == _msgSender(),\n \"unauthorized commitment creator\"\n );\n\n commitments[commitmentId_] = _commitment;\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitments[commitmentId_]);\n\n //the borrower allowlists is in a different storage space so we append them to the array with this method s\n _addBorrowersToCommitmentAllowlist(commitmentId_, _borrowerAddressList);\n\n emit CreatedCommitment(\n commitmentId_,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the commitment of a lender to a market.\n * @param _commitmentId The Id of the commitment to update.\n * @param _commitment The new commitment data expressed as a struct\n */\n function updateCommitment(\n uint256 _commitmentId,\n Commitment calldata _commitment\n ) public commitmentLender(_commitmentId) {\n require(\n _commitment.lender == _msgSender(),\n \"Commitment lender cannot be updated.\"\n );\n\n require(\n _commitment.principalTokenAddress ==\n commitments[_commitmentId].principalTokenAddress,\n \"Principal token address cannot be updated.\"\n );\n require(\n _commitment.marketId == commitments[_commitmentId].marketId,\n \"Market Id cannot be updated.\"\n );\n\n commitments[_commitmentId] = _commitment;\n\n //make sure the commitment data still adheres to required specifications and limits\n validateCommitment(commitments[_commitmentId]);\n\n emit UpdatedCommitment(\n _commitmentId,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function addCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _addBorrowersToCommitmentAllowlist(_commitmentId, _borrowerAddressList);\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function removeCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _removeBorrowersFromCommitmentAllowlist(\n _commitmentId,\n _borrowerAddressList\n );\n }\n\n /**\n * @notice Adds a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _addBorrowersToCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].add(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _removeBorrowersFromCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].remove(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes the commitment of a lender to a market.\n * @param _commitmentId The id of the commitment to delete.\n */\n function deleteCommitment(uint256 _commitmentId)\n public\n commitmentLender(_commitmentId)\n {\n delete commitments[_commitmentId];\n delete commitmentBorrowersList[_commitmentId];\n emit DeletedCommitment(_commitmentId);\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration\n ) external returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType <=\n CommitmentCollateralType.ERC1155_ANY_ID,\n \"Invalid commitment collateral type\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _interestRate,\n _loanDuration\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @param _merkleProof An array of bytes32 which are the roots down the merkle tree, the merkle proof.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) external returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF ||\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC1155_MERKLE_PROOF,\n \"Invalid commitment collateral type\"\n );\n\n bytes32 _merkleRoot = bytes32(\n commitments[_commitmentId].collateralTokenId\n );\n bytes32 _leaf = keccak256(abi.encodePacked(_collateralTokenId));\n\n //make sure collateral token id is a leaf within the proof\n require(\n MerkleProofUpgradeable.verifyCalldata(\n _merkleProof,\n _merkleRoot,\n _leaf\n ),\n \"Invalid proof\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _interestRate,\n _loanDuration\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function _acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration\n ) internal returns (uint256 bidId) {\n address borrower = _msgSender();\n\n Commitment storage commitment = commitments[_commitmentId];\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitment);\n\n //the collateral token of the commitment should be the same as the acceptor expects\n require(\n _collateralTokenAddress == commitment.collateralTokenAddress,\n \"Mismatching collateral token\"\n );\n //the interest rate must be at least as high has the commitment demands. The borrower can use a higher interest rate although that would not be beneficial to the borrower.\n require(\n _interestRate >= commitment.minInterestRate,\n \"Invalid interest rate\"\n );\n //the loan duration must be less than the commitment max loan duration. The lender who made the commitment expects the money to be returned before this window.\n require(\n _loanDuration <= commitment.maxDuration,\n \"Invalid loan max duration\"\n );\n\n require(\n commitmentPrincipalAccepted[bidId] <= commitment.maxPrincipal,\n \"Invalid loan max principal\"\n );\n\n require(\n commitmentBorrowersList[_commitmentId].length() == 0 ||\n commitmentBorrowersList[_commitmentId].contains(borrower),\n \"unauthorized commitment borrower\"\n );\n //require that the borrower accepting the commitment cannot borrow more than the commitments max principal\n if (_principalAmount > commitment.maxPrincipal) {\n revert InsufficientCommitmentAllocation({\n allocated: commitment.maxPrincipal,\n requested: _principalAmount\n });\n }\n\n uint256 requiredCollateral = getRequiredCollateral(\n _principalAmount,\n commitment.maxPrincipalPerCollateralAmount,\n commitment.collateralTokenType,\n commitment.collateralTokenAddress,\n commitment.principalTokenAddress\n );\n\n if (_collateralAmount < requiredCollateral) {\n revert InsufficientBorrowerCollateral({\n required: requiredCollateral,\n actual: _collateralAmount\n });\n }\n\n //ERC721 assets must have a quantity of 1\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_ANY_ID ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n require(\n _collateralAmount == 1,\n \"invalid commitment collateral amount for ERC721\"\n );\n }\n\n //ERC721 and ERC1155 types strictly enforce a specific token Id. ERC721_ANY and ERC1155_ANY do not.\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType == CommitmentCollateralType.ERC1155\n ) {\n require(\n commitment.collateralTokenId == _collateralTokenId,\n \"invalid commitment collateral tokenId\"\n );\n }\n\n commitmentPrincipalAccepted[_commitmentId] += _principalAmount;\n\n require(\n commitmentPrincipalAccepted[_commitmentId] <=\n commitment.maxPrincipal,\n \"Exceeds max principal of commitment\"\n );\n\n bidId = _submitBidFromCommitment(\n borrower,\n commitment.marketId,\n commitment.principalTokenAddress,\n _principalAmount,\n commitment.collateralTokenAddress,\n _collateralAmount,\n _collateralTokenId,\n commitment.collateralTokenType,\n _loanDuration,\n _interestRate\n );\n\n _acceptBid(bidId, commitment.lender);\n\n emit ExercisedCommitment(\n _commitmentId,\n borrower,\n _principalAmount,\n bidId\n );\n }\n\n /**\n * @notice Calculate the amount of collateral required to borrow a loan with _principalAmount of principal\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _maxPrincipalPerCollateralAmount The ratio for the amount of principal that can be borrowed for each amount of collateral. This is expanded additionally by the principal decimals.\n * @param _collateralTokenType The type of collateral for the loan either ERC20, ERC721, ERC1155, or None.\n * @param _collateralTokenAddress The contract address for the collateral for the loan.\n * @param _principalTokenAddress The contract address for the principal for the loan.\n */\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount,\n CommitmentCollateralType _collateralTokenType,\n address _collateralTokenAddress,\n address _principalTokenAddress\n ) public view virtual returns (uint256) {\n if (_collateralTokenType == CommitmentCollateralType.NONE) {\n return 0;\n }\n\n uint8 collateralDecimals;\n uint8 principalDecimals = IERC20MetadataUpgradeable(\n _principalTokenAddress\n ).decimals();\n\n if (_collateralTokenType == CommitmentCollateralType.ERC20) {\n collateralDecimals = IERC20MetadataUpgradeable(\n _collateralTokenAddress\n ).decimals();\n }\n\n /*\n * The principalAmount is expanded by (collateralDecimals+principalDecimals) to increase precision\n * and then it is divided by _maxPrincipalPerCollateralAmount which should already been expanded by principalDecimals\n */\n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n (10**(collateralDecimals + principalDecimals)),\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n );\n }\n\n /**\n * @notice Return the array of borrowers that are allowlisted for a commitment\n * @param _commitmentId The commitment id for the commitment to query.\n * @return borrowers_ An array of addresses restricted to accept the commitment. Empty array means unrestricted.\n */\n function getCommitmentBorrowers(uint256 _commitmentId)\n external\n view\n returns (address[] memory borrowers_)\n {\n borrowers_ = commitmentBorrowersList[_commitmentId].values();\n }\n\n /**\n * @notice Internal function to submit a bid to the lending protocol using a commitment\n * @param _borrower The address of the borrower for the loan.\n * @param _marketId The id for the market of the loan in the lending protocol.\n * @param _principalTokenAddress The contract address for the principal token.\n * @param _principalAmount The amount of principal to borrow for the loan.\n * @param _collateralTokenAddress The contract address for the collateral token.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId for the collateral (if it is ERC721 or ERC1155).\n * @param _collateralTokenType The type of collateral token (ERC20,ERC721,ERC1177,None).\n * @param _loanDuration The duration of the loan in seconds delta. Must be longer than loan payment cycle for the market.\n * @param _interestRate The amount of interest APY for the loan expressed in basis points.\n */\n function _submitBidFromCommitment(\n address _borrower,\n uint256 _marketId,\n address _principalTokenAddress,\n uint256 _principalAmount,\n address _collateralTokenAddress,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n CommitmentCollateralType _collateralTokenType,\n uint32 _loanDuration,\n uint16 _interestRate\n ) internal returns (uint256 bidId) {\n CreateLoanArgs memory createLoanArgs;\n createLoanArgs.marketId = _marketId;\n createLoanArgs.lendingToken = _principalTokenAddress;\n createLoanArgs.principal = _principalAmount;\n createLoanArgs.duration = _loanDuration;\n createLoanArgs.interestRate = _interestRate;\n\n Collateral[] memory collateralInfo;\n if (_collateralTokenType != CommitmentCollateralType.NONE) {\n collateralInfo = new Collateral[](1);\n collateralInfo[0] = Collateral({\n _collateralType: _getEscrowCollateralType(_collateralTokenType),\n _tokenId: _collateralTokenId,\n _amount: _collateralAmount,\n _collateralAddress: _collateralTokenAddress\n });\n }\n\n bidId = _submitBidWithCollateral(\n createLoanArgs,\n collateralInfo,\n _borrower\n );\n }\n\n /**\n * @notice Return the collateral type based on the commitmentcollateral type. Collateral type is used in the base lending protocol.\n * @param _type The type of collateral to be used for the loan.\n */\n function _getEscrowCollateralType(CommitmentCollateralType _type)\n internal\n pure\n returns (CollateralType)\n {\n if (_type == CommitmentCollateralType.ERC20) {\n return CollateralType.ERC20;\n }\n if (\n _type == CommitmentCollateralType.ERC721 ||\n _type == CommitmentCollateralType.ERC721_ANY_ID ||\n _type == CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n return CollateralType.ERC721;\n }\n if (\n _type == CommitmentCollateralType.ERC1155 ||\n _type == CommitmentCollateralType.ERC1155_ANY_ID ||\n _type == CommitmentCollateralType.ERC1155_MERKLE_PROOF\n ) {\n return CollateralType.ERC1155;\n }\n\n revert(\"Unknown Collateral Type\");\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_G2.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"../TellerV2MarketForwarder_G2.sol\";\n\n// Interfaces\nimport \"../interfaces/ICollateralManager.sol\";\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\nimport { Collateral, CollateralType } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\n\ncontract LenderCommitmentForwarder_G2 is\n TellerV2MarketForwarder_G2,\n ILenderCommitmentForwarder\n{\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n // CommitmentId => commitment\n mapping(uint256 => Commitment) public commitments;\n\n uint256 commitmentCount;\n\n //https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/structs/EnumerableSetUpgradeable.sol\n mapping(uint256 => EnumerableSetUpgradeable.AddressSet)\n internal commitmentBorrowersList;\n\n mapping(uint256 => uint256) public commitmentPrincipalAccepted;\n\n /**\n * @notice This event is emitted when a lender's commitment is created.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event CreatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when a lender's commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event UpdatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when the allowed borrowers for a commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n */\n event UpdatedCommitmentBorrowers(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment has been deleted.\n * @param commitmentId The id of the commitment that was deleted.\n */\n event DeletedCommitment(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment is exercised for a loan.\n * @param commitmentId The id of the commitment that was exercised.\n * @param borrower The address of the borrower.\n * @param tokenAmount The amount of the asset being committed.\n * @param bidId The bid id for the loan from TellerV2.\n */\n event ExercisedCommitment(\n uint256 indexed commitmentId,\n address borrower,\n uint256 tokenAmount,\n uint256 bidId\n );\n\n error InsufficientCommitmentAllocation(\n uint256 allocated,\n uint256 requested\n );\n error InsufficientBorrowerCollateral(uint256 required, uint256 actual);\n\n /** Modifiers **/\n\n modifier commitmentLender(uint256 _commitmentId) {\n require(\n commitments[_commitmentId].lender == _msgSender(),\n \"unauthorized commitment lender\"\n );\n _;\n }\n\n function validateCommitment(Commitment storage _commitment) internal {\n require(\n _commitment.expiration > uint32(block.timestamp),\n \"expired commitment\"\n );\n require(\n _commitment.maxPrincipal > 0,\n \"commitment principal allocation 0\"\n );\n\n if (_commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n require(\n _commitment.maxPrincipalPerCollateralAmount > 0,\n \"commitment collateral ratio 0\"\n );\n\n if (\n _commitment.collateralTokenType ==\n CommitmentCollateralType.ERC20\n ) {\n require(\n _commitment.collateralTokenId == 0,\n \"commitment collateral token id must be 0 for ERC20\"\n );\n }\n }\n }\n\n /** External Functions **/\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _protocolAddress, address _marketRegistry)\n TellerV2MarketForwarder_G2(_protocolAddress, _marketRegistry)\n {}\n\n /**\n * @notice Creates a loan commitment from a lender for a market.\n * @param _commitment The new commitment data expressed as a struct\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n * @return commitmentId_ returns the commitmentId for the created commitment\n */\n function createCommitment(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList\n ) public returns (uint256 commitmentId_) {\n commitmentId_ = commitmentCount++;\n\n require(\n _commitment.lender == _msgSender(),\n \"unauthorized commitment creator\"\n );\n\n commitments[commitmentId_] = _commitment;\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitments[commitmentId_]);\n\n //the borrower allowlists is in a different storage space so we append them to the array with this method s\n _addBorrowersToCommitmentAllowlist(commitmentId_, _borrowerAddressList);\n\n emit CreatedCommitment(\n commitmentId_,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the commitment of a lender to a market.\n * @param _commitmentId The Id of the commitment to update.\n * @param _commitment The new commitment data expressed as a struct\n */\n function updateCommitment(\n uint256 _commitmentId,\n Commitment calldata _commitment\n ) public commitmentLender(_commitmentId) {\n require(\n _commitment.lender == _msgSender(),\n \"Commitment lender cannot be updated.\"\n );\n\n require(\n _commitment.principalTokenAddress ==\n commitments[_commitmentId].principalTokenAddress,\n \"Principal token address cannot be updated.\"\n );\n require(\n _commitment.marketId == commitments[_commitmentId].marketId,\n \"Market Id cannot be updated.\"\n );\n\n commitments[_commitmentId] = _commitment;\n\n //make sure the commitment data still adheres to required specifications and limits\n validateCommitment(commitments[_commitmentId]);\n\n emit UpdatedCommitment(\n _commitmentId,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function addCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _addBorrowersToCommitmentAllowlist(_commitmentId, _borrowerAddressList);\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function removeCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _removeBorrowersFromCommitmentAllowlist(\n _commitmentId,\n _borrowerAddressList\n );\n }\n\n /**\n * @notice Adds a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _addBorrowersToCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].add(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _removeBorrowersFromCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].remove(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes the commitment of a lender to a market.\n * @param _commitmentId The id of the commitment to delete.\n */\n function deleteCommitment(uint256 _commitmentId)\n public\n commitmentLender(_commitmentId)\n {\n delete commitments[_commitmentId];\n delete commitmentBorrowersList[_commitmentId];\n emit DeletedCommitment(_commitmentId);\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType <=\n CommitmentCollateralType.ERC1155_ANY_ID,\n \"Invalid commitment collateral type\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n return\n acceptCommitmentWithRecipient(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n address(0),\n _interestRate,\n _loanDuration\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @param _merkleProof An array of bytes32 which are the roots down the merkle tree, the merkle proof.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF ||\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC1155_MERKLE_PROOF,\n \"Invalid commitment collateral type\"\n );\n\n bytes32 _merkleRoot = bytes32(\n commitments[_commitmentId].collateralTokenId\n );\n bytes32 _leaf = keccak256(abi.encodePacked(_collateralTokenId));\n\n //make sure collateral token id is a leaf within the proof\n require(\n MerkleProofUpgradeable.verifyCalldata(\n _merkleProof,\n _merkleRoot,\n _leaf\n ),\n \"Invalid proof\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function acceptCommitmentWithProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n return\n acceptCommitmentWithRecipientAndProof(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n address(0),\n _interestRate,\n _loanDuration,\n _merkleProof\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function _acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) internal returns (uint256 bidId) {\n Commitment storage commitment = commitments[_commitmentId];\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitment);\n\n //the collateral token of the commitment should be the same as the acceptor expects\n require(\n _collateralTokenAddress == commitment.collateralTokenAddress,\n \"Mismatching collateral token\"\n );\n //the interest rate must be at least as high has the commitment demands. The borrower can use a higher interest rate although that would not be beneficial to the borrower.\n require(\n _interestRate >= commitment.minInterestRate,\n \"Invalid interest rate\"\n );\n //the loan duration must be less than the commitment max loan duration. The lender who made the commitment expects the money to be returned before this window.\n require(\n _loanDuration <= commitment.maxDuration,\n \"Invalid loan max duration\"\n );\n\n require(\n commitmentPrincipalAccepted[bidId] <= commitment.maxPrincipal,\n \"Invalid loan max principal\"\n );\n\n require(\n commitmentBorrowersList[_commitmentId].length() == 0 ||\n commitmentBorrowersList[_commitmentId].contains(_msgSender()),\n \"unauthorized commitment borrower\"\n );\n //require that the borrower accepting the commitment cannot borrow more than the commitments max principal\n if (_principalAmount > commitment.maxPrincipal) {\n revert InsufficientCommitmentAllocation({\n allocated: commitment.maxPrincipal,\n requested: _principalAmount\n });\n }\n\n uint256 requiredCollateral = getRequiredCollateral(\n _principalAmount,\n commitment.maxPrincipalPerCollateralAmount,\n commitment.collateralTokenType,\n commitment.collateralTokenAddress,\n commitment.principalTokenAddress\n );\n\n if (_collateralAmount < requiredCollateral) {\n revert InsufficientBorrowerCollateral({\n required: requiredCollateral,\n actual: _collateralAmount\n });\n }\n\n //ERC721 assets must have a quantity of 1\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_ANY_ID ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n require(\n _collateralAmount == 1,\n \"invalid commitment collateral amount for ERC721\"\n );\n }\n\n //ERC721 and ERC1155 types strictly enforce a specific token Id. ERC721_ANY and ERC1155_ANY do not.\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType == CommitmentCollateralType.ERC1155\n ) {\n require(\n commitment.collateralTokenId == _collateralTokenId,\n \"invalid commitment collateral tokenId\"\n );\n }\n\n commitmentPrincipalAccepted[_commitmentId] += _principalAmount;\n\n require(\n commitmentPrincipalAccepted[_commitmentId] <=\n commitment.maxPrincipal,\n \"Exceeds max principal of commitment\"\n );\n\n CreateLoanArgs memory createLoanArgs;\n createLoanArgs.marketId = commitment.marketId;\n createLoanArgs.lendingToken = commitment.principalTokenAddress;\n createLoanArgs.principal = _principalAmount;\n createLoanArgs.duration = _loanDuration;\n createLoanArgs.interestRate = _interestRate;\n createLoanArgs.recipient = _recipient;\n if (commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n createLoanArgs.collateral = new Collateral[](1);\n createLoanArgs.collateral[0] = Collateral({\n _collateralType: _getEscrowCollateralType(\n commitment.collateralTokenType\n ),\n _tokenId: _collateralTokenId,\n _amount: _collateralAmount,\n _collateralAddress: commitment.collateralTokenAddress\n });\n }\n\n bidId = _submitBidWithCollateral(createLoanArgs, _msgSender());\n\n _acceptBid(bidId, commitment.lender);\n\n emit ExercisedCommitment(\n _commitmentId,\n _msgSender(),\n _principalAmount,\n bidId\n );\n }\n\n /**\n * @notice Calculate the amount of collateral required to borrow a loan with _principalAmount of principal\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _maxPrincipalPerCollateralAmount The ratio for the amount of principal that can be borrowed for each amount of collateral. This is expanded additionally by the principal decimals.\n * @param _collateralTokenType The type of collateral for the loan either ERC20, ERC721, ERC1155, or None.\n * @param _collateralTokenAddress The contract address for the collateral for the loan.\n * @param _principalTokenAddress The contract address for the principal for the loan.\n */\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount,\n CommitmentCollateralType _collateralTokenType,\n address _collateralTokenAddress,\n address _principalTokenAddress\n ) public view virtual returns (uint256) {\n if (_collateralTokenType == CommitmentCollateralType.NONE) {\n return 0;\n }\n\n uint8 collateralDecimals;\n uint8 principalDecimals = IERC20MetadataUpgradeable(\n _principalTokenAddress\n ).decimals();\n\n if (_collateralTokenType == CommitmentCollateralType.ERC20) {\n collateralDecimals = IERC20MetadataUpgradeable(\n _collateralTokenAddress\n ).decimals();\n }\n\n /*\n * The principalAmount is expanded by (collateralDecimals+principalDecimals) to increase precision\n * and then it is divided by _maxPrincipalPerCollateralAmount which should already been expanded by principalDecimals\n */\n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n (10**(collateralDecimals + principalDecimals)),\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n );\n }\n\n /**\n * @notice Return the array of borrowers that are allowlisted for a commitment\n * @param _commitmentId The commitment id for the commitment to query.\n * @return borrowers_ An array of addresses restricted to accept the commitment. Empty array means unrestricted.\n */\n function getCommitmentBorrowers(uint256 _commitmentId)\n external\n view\n returns (address[] memory borrowers_)\n {\n borrowers_ = commitmentBorrowersList[_commitmentId].values();\n }\n\n /**\n * @notice Return the collateral type based on the commitmentcollateral type. Collateral type is used in the base lending protocol.\n * @param _type The type of collateral to be used for the loan.\n */\n function _getEscrowCollateralType(CommitmentCollateralType _type)\n internal\n pure\n returns (CollateralType)\n {\n if (_type == CommitmentCollateralType.ERC20) {\n return CollateralType.ERC20;\n }\n if (\n _type == CommitmentCollateralType.ERC721 ||\n _type == CommitmentCollateralType.ERC721_ANY_ID ||\n _type == CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n return CollateralType.ERC721;\n }\n if (\n _type == CommitmentCollateralType.ERC1155 ||\n _type == CommitmentCollateralType.ERC1155_ANY_ID ||\n _type == CommitmentCollateralType.ERC1155_MERKLE_PROOF\n ) {\n return CollateralType.ERC1155;\n }\n\n revert(\"Unknown Collateral Type\");\n }\n\n function getCommitmentMarketId(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitments[_commitmentId].marketId;\n }\n\n function getCommitmentLender(uint256 _commitmentId)\n external\n view\n returns (address)\n {\n return commitments[_commitmentId].lender;\n }\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitmentPrincipalAccepted[_commitmentId];\n }\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitments[_commitmentId].maxPrincipal;\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_G3.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"./LenderCommitmentForwarder_G2.sol\";\nimport \"./extensions/ExtensionsContextUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract LenderCommitmentForwarder_G3 is\n LenderCommitmentForwarder_G2,\n ExtensionsContextUpgradeable\n{\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _tellerV2, address _marketRegistry)\n LenderCommitmentForwarder_G2(_tellerV2, _marketRegistry)\n {}\n\n function _msgSender()\n internal\n view\n virtual\n override(ContextUpgradeable, ExtensionsContextUpgradeable)\n returns (address sender)\n {\n return ExtensionsContextUpgradeable._msgSender();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder_U1.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"../TellerV2MarketForwarder_G2.sol\";\n\n// Interfaces\nimport \"../interfaces/ICollateralManager.sol\";\nimport \"../interfaces/ILenderCommitmentForwarder_U1.sol\";\nimport \"./extensions/ExtensionsContextUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\n\nimport { Collateral, CollateralType } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\n\nimport \"../interfaces/uniswap/IUniswapV3Pool.sol\";\nimport \"../interfaces/uniswap/IUniswapV3Factory.sol\";\n\nimport \"../libraries/uniswap/TickMath.sol\";\nimport \"../libraries/uniswap/FixedPoint96.sol\";\nimport \"../libraries/uniswap/FullMath.sol\";\n\nimport \"../libraries/NumbersLib.sol\";\n\nimport \"./extensions/ExtensionsContextUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n\n\n/*\n\nOnly do decimal expansion if it is an ERC20 not anything else !! \n\n*/\n\ncontract LenderCommitmentForwarder_U1 is\n ExtensionsContextUpgradeable, //this should always be first for upgradeability\n TellerV2MarketForwarder_G2,\n ILenderCommitmentForwarder_U1\n{\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n using NumbersLib for uint256;\n\n // CommitmentId => commitment\n mapping(uint256 => Commitment) public commitments;\n\n uint256 commitmentCount;\n\n //https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/structs/EnumerableSetUpgradeable.sol\n mapping(uint256 => EnumerableSetUpgradeable.AddressSet)\n internal commitmentBorrowersList;\n\n mapping(uint256 => uint256) public commitmentPrincipalAccepted;\n\n mapping(uint256 => PoolRouteConfig[]) internal commitmentUniswapPoolRoutes;\n\n mapping(uint256 => uint16) internal commitmentPoolOracleLtvRatio;\n\n //does not take a storage slot\n address immutable UNISWAP_V3_FACTORY;\n\n uint256 immutable STANDARD_EXPANSION_FACTOR = 1e18;\n\n /**\n * @notice This event is emitted when a lender's commitment is created.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event CreatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when a lender's commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n * @param lender The address of the lender.\n * @param marketId The Id of the market the commitment applies to.\n * @param lendingToken The address of the asset being committed.\n * @param tokenAmount The amount of the asset being committed.\n */\n event UpdatedCommitment(\n uint256 indexed commitmentId,\n address lender,\n uint256 marketId,\n address lendingToken,\n uint256 tokenAmount\n );\n\n /**\n * @notice This event is emitted when the allowed borrowers for a commitment is updated.\n * @param commitmentId The id of the commitment that was updated.\n */\n event UpdatedCommitmentBorrowers(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment has been deleted.\n * @param commitmentId The id of the commitment that was deleted.\n */\n event DeletedCommitment(uint256 indexed commitmentId);\n\n /**\n * @notice This event is emitted when a lender's commitment is exercised for a loan.\n * @param commitmentId The id of the commitment that was exercised.\n * @param borrower The address of the borrower.\n * @param tokenAmount The amount of the asset being committed.\n * @param bidId The bid id for the loan from TellerV2.\n */\n event ExercisedCommitment(\n uint256 indexed commitmentId,\n address borrower,\n uint256 tokenAmount,\n uint256 bidId\n );\n\n error InsufficientCommitmentAllocation(\n uint256 allocated,\n uint256 requested\n );\n error InsufficientBorrowerCollateral(uint256 required, uint256 actual);\n\n /** Modifiers **/\n\n modifier commitmentLender(uint256 _commitmentId) {\n require(\n commitments[_commitmentId].lender == _msgSender(),\n \"unauthorized commitment lender\"\n );\n _;\n }\n\n function validateCommitment(Commitment storage _commitment) internal {\n require(\n _commitment.expiration > uint32(block.timestamp),\n \"expired commitment\"\n );\n require(\n _commitment.maxPrincipal > 0,\n \"commitment principal allocation 0\"\n );\n\n if (_commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n require(\n _commitment.maxPrincipalPerCollateralAmount > 0,\n \"commitment collateral ratio 0\"\n );\n\n if (\n _commitment.collateralTokenType ==\n CommitmentCollateralType.ERC20\n ) {\n require(\n _commitment.collateralTokenId == 0,\n \"commitment collateral token id must be 0 for ERC20\"\n );\n }\n }\n }\n\n /** External Functions **/\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _protocolAddress,\n address _marketRegistry,\n address _uniswapV3Factory\n ) TellerV2MarketForwarder_G2(_protocolAddress, _marketRegistry) {\n UNISWAP_V3_FACTORY = _uniswapV3Factory;\n }\n\n /**\n * @notice Creates a loan commitment from a lender for a market.\n * @param _commitment The new commitment data expressed as a struct\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n * @return commitmentId_ returns the commitmentId for the created commitment\n */\n function createCommitmentWithUniswap(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList,\n PoolRouteConfig[] calldata _poolRoutes,\n uint16 _poolOracleLtvRatio //generally always between 0 and 100 % , 0 to 10000\n ) public returns (uint256 commitmentId_) {\n commitmentId_ = commitmentCount++;\n \n require(\n _commitment.lender == _msgSender(),\n \"unauthorized commitment creator\"\n );\n\n commitments[commitmentId_] = _commitment;\n\n require(_poolRoutes.length == 0 || _commitment.collateralTokenType == CommitmentCollateralType.ERC20 , \"can only use pool routes with ERC20 collateral\");\n\n\n //routes length of 0 means ignore price oracle limits\n require(_poolRoutes.length <= 2, \"invalid pool routes length\");\n\n \n \n\n for (uint256 i = 0; i < _poolRoutes.length; i++) {\n commitmentUniswapPoolRoutes[commitmentId_].push(_poolRoutes[i]);\n }\n\n commitmentPoolOracleLtvRatio[commitmentId_] = _poolOracleLtvRatio;\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitments[commitmentId_]);\n\n //the borrower allowlists is in a different storage space so we append them to the array with this method s\n _addBorrowersToCommitmentAllowlist(commitmentId_, _borrowerAddressList);\n\n emit CreatedCommitment(\n commitmentId_,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the commitment of a lender to a market.\n * @param _commitmentId The Id of the commitment to update.\n * @param _commitment The new commitment data expressed as a struct\n */\n function updateCommitment(\n uint256 _commitmentId,\n Commitment calldata _commitment\n ) public commitmentLender(_commitmentId) {\n require(\n _commitment.lender == _msgSender(),\n \"Commitment lender cannot be updated.\"\n );\n\n require(\n _commitment.principalTokenAddress ==\n commitments[_commitmentId].principalTokenAddress,\n \"Principal token address cannot be updated.\"\n );\n require(\n _commitment.marketId == commitments[_commitmentId].marketId,\n \"Market Id cannot be updated.\"\n );\n\n commitments[_commitmentId] = _commitment;\n\n //make sure the commitment data still adheres to required specifications and limits\n validateCommitment(commitments[_commitmentId]);\n\n emit UpdatedCommitment(\n _commitmentId,\n _commitment.lender,\n _commitment.marketId,\n _commitment.principalTokenAddress,\n _commitment.maxPrincipal\n );\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function addCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _addBorrowersToCommitmentAllowlist(_commitmentId, _borrowerAddressList);\n }\n\n /**\n * @notice Updates the borrowers allowed to accept a commitment\n * @param _commitmentId The Id of the commitment to update.\n * @param _borrowerAddressList The array of borrowers that are allowed to accept loans using this commitment\n */\n function removeCommitmentBorrowers(\n uint256 _commitmentId,\n address[] calldata _borrowerAddressList\n ) public commitmentLender(_commitmentId) {\n _removeBorrowersFromCommitmentAllowlist(\n _commitmentId,\n _borrowerAddressList\n );\n }\n\n /**\n * @notice Adds a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _addBorrowersToCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].add(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes a borrower to the allowlist for a commmitment.\n * @param _commitmentId The id of the commitment that will allow the new borrower\n * @param _borrowerArray the address array of the borrowers that will be allowed to accept loans using the commitment\n */\n function _removeBorrowersFromCommitmentAllowlist(\n uint256 _commitmentId,\n address[] calldata _borrowerArray\n ) internal {\n for (uint256 i = 0; i < _borrowerArray.length; i++) {\n commitmentBorrowersList[_commitmentId].remove(_borrowerArray[i]);\n }\n emit UpdatedCommitmentBorrowers(_commitmentId);\n }\n\n /**\n * @notice Removes the commitment of a lender to a market.\n * @param _commitmentId The id of the commitment to delete.\n */\n function deleteCommitment(uint256 _commitmentId)\n public\n commitmentLender(_commitmentId)\n {\n delete commitments[_commitmentId];\n delete commitmentBorrowersList[_commitmentId];\n emit DeletedCommitment(_commitmentId);\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType <=\n CommitmentCollateralType.ERC1155_ANY_ID,\n \"Invalid commitment collateral type\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n return\n acceptCommitmentWithRecipient(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n address(0),\n _interestRate,\n _loanDuration\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @param _merkleProof An array of bytes32 which are the roots down the merkle tree, the merkle proof.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n require(\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF ||\n commitments[_commitmentId].collateralTokenType ==\n CommitmentCollateralType.ERC1155_MERKLE_PROOF,\n \"Invalid commitment collateral type\"\n );\n\n bytes32 _merkleRoot = bytes32(\n commitments[_commitmentId].collateralTokenId\n );\n bytes32 _leaf = keccak256(abi.encodePacked(_collateralTokenId));\n\n //make sure collateral token id is a leaf within the proof\n require(\n MerkleProofUpgradeable.verifyCalldata(\n _merkleProof,\n _merkleRoot,\n _leaf\n ),\n \"Invalid proof\"\n );\n\n return\n _acceptCommitment(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function acceptCommitmentWithProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n return\n acceptCommitmentWithRecipientAndProof(\n _commitmentId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n address(0),\n _interestRate,\n _loanDuration,\n _merkleProof\n );\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _commitmentId The id of the commitment being accepted.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function _acceptCommitment(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) internal returns (uint256 bidId) {\n Commitment storage commitment = commitments[_commitmentId];\n\n //make sure the commitment data adheres to required specifications and limits\n validateCommitment(commitment);\n\n //the collateral token of the commitment should be the same as the acceptor expects\n require(\n _collateralTokenAddress == commitment.collateralTokenAddress,\n \"Mismatching collateral token\"\n );\n\n //the interest rate must be at least as high has the commitment demands. The borrower can use a higher interest rate although that would not be beneficial to the borrower.\n require(\n _interestRate >= commitment.minInterestRate,\n \"Invalid interest rate\"\n );\n //the loan duration must be less than the commitment max loan duration. The lender who made the commitment expects the money to be returned before this window.\n require(\n _loanDuration <= commitment.maxDuration,\n \"Invalid loan max duration\"\n );\n\n require(\n commitmentPrincipalAccepted[bidId] <= commitment.maxPrincipal,\n \"Invalid loan max principal\"\n );\n\n require(\n commitmentBorrowersList[_commitmentId].length() == 0 ||\n commitmentBorrowersList[_commitmentId].contains(_msgSender()),\n \"unauthorized commitment borrower\"\n );\n //require that the borrower accepting the commitment cannot borrow more than the commitments max principal\n if (_principalAmount > commitment.maxPrincipal) {\n revert InsufficientCommitmentAllocation({\n allocated: commitment.maxPrincipal,\n requested: _principalAmount\n });\n }\n\n {\n uint256 scaledPoolOraclePrice = getUniswapPriceRatioForPoolRoutes(\n commitmentUniswapPoolRoutes[_commitmentId]\n ).percent(commitmentPoolOracleLtvRatio[_commitmentId]);\n\n bool usePoolRoutes = commitmentUniswapPoolRoutes[_commitmentId]\n .length > 0;\n\n //use the worst case ratio either the oracle or the static ratio\n uint256 maxPrincipalPerCollateralAmount = usePoolRoutes\n ? Math.min(\n scaledPoolOraclePrice,\n commitment.maxPrincipalPerCollateralAmount\n )\n : commitment.maxPrincipalPerCollateralAmount;\n\n uint256 requiredCollateral = getRequiredCollateral(\n _principalAmount,\n maxPrincipalPerCollateralAmount,\n commitment.collateralTokenType\n );\n\n if (_collateralAmount < requiredCollateral) {\n revert InsufficientBorrowerCollateral({\n required: requiredCollateral,\n actual: _collateralAmount\n });\n }\n }\n\n //ERC721 assets must have a quantity of 1\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_ANY_ID ||\n commitment.collateralTokenType ==\n CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n require(\n _collateralAmount == 1,\n \"invalid commitment collateral amount for ERC721\"\n );\n }\n\n //ERC721 and ERC1155 types strictly enforce a specific token Id. ERC721_ANY and ERC1155_ANY do not.\n if (\n commitment.collateralTokenType == CommitmentCollateralType.ERC721 ||\n commitment.collateralTokenType == CommitmentCollateralType.ERC1155\n ) {\n require(\n commitment.collateralTokenId == _collateralTokenId,\n \"invalid commitment collateral tokenId\"\n );\n }\n\n commitmentPrincipalAccepted[_commitmentId] += _principalAmount;\n\n require(\n commitmentPrincipalAccepted[_commitmentId] <=\n commitment.maxPrincipal,\n \"Exceeds max principal of commitment\"\n );\n\n CreateLoanArgs memory createLoanArgs;\n createLoanArgs.marketId = commitment.marketId;\n createLoanArgs.lendingToken = commitment.principalTokenAddress;\n createLoanArgs.principal = _principalAmount;\n createLoanArgs.duration = _loanDuration;\n createLoanArgs.interestRate = _interestRate;\n createLoanArgs.recipient = _recipient;\n if (commitment.collateralTokenType != CommitmentCollateralType.NONE) {\n createLoanArgs.collateral = new Collateral[](1);\n createLoanArgs.collateral[0] = Collateral({\n _collateralType: _getEscrowCollateralType(\n commitment.collateralTokenType\n ),\n _tokenId: _collateralTokenId,\n _amount: _collateralAmount,\n _collateralAddress: commitment.collateralTokenAddress\n });\n }\n\n bidId = _submitBidWithCollateral(createLoanArgs, _msgSender());\n\n _acceptBid(bidId, commitment.lender);\n\n emit ExercisedCommitment(\n _commitmentId,\n _msgSender(),\n _principalAmount,\n bidId\n );\n }\n\n /**\n * @notice Calculate the amount of collateral required to borrow a loan with _principalAmount of principal\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _maxPrincipalPerCollateralAmount The ratio for the amount of principal that can be borrowed for each amount of collateral. \n * @param _collateralTokenType The type of collateral for the loan either ERC20, ERC721, ERC1155, or None.\n \n */\n function getRequiredCollateral(\n uint256 _principalAmount,\n uint256 _maxPrincipalPerCollateralAmount,\n CommitmentCollateralType _collateralTokenType\n ) public view virtual returns (uint256) {\n if (_collateralTokenType == CommitmentCollateralType.NONE) {\n return 0;\n }\n\n if (_collateralTokenType == CommitmentCollateralType.ERC20) {\n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n STANDARD_EXPANSION_FACTOR,\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n );\n }\n\n //for NFTs, do not use the uniswap expansion factor \n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n 1,\n _maxPrincipalPerCollateralAmount,\n MathUpgradeable.Rounding.Up\n );\n\n \n }\n\n /**\n * @dev Returns the PoolRouteConfig at a specific index for a given commitmentId from the commitmentUniswapPoolRoutes mapping.\n * @param commitmentId The commitmentId to access the mapping.\n * @param index The index in the array of PoolRouteConfigs for the given commitmentId.\n * @return The PoolRouteConfig at the specified index.\n */\n function getCommitmentUniswapPoolRoute(uint256 commitmentId, uint index)\n public\n view\n returns (PoolRouteConfig memory)\n {\n require(\n index < commitmentUniswapPoolRoutes[commitmentId].length,\n \"Index out of bounds\"\n );\n return commitmentUniswapPoolRoutes[commitmentId][index];\n }\n\n /**\n * @dev Returns the entire array of PoolRouteConfigs for a given commitmentId from the commitmentUniswapPoolRoutes mapping.\n * @param commitmentId The commitmentId to access the mapping.\n * @return The entire array of PoolRouteConfigs for the specified commitmentId.\n */\n function getAllCommitmentUniswapPoolRoutes(uint256 commitmentId)\n public\n view\n returns (PoolRouteConfig[] memory)\n {\n return commitmentUniswapPoolRoutes[commitmentId];\n }\n\n /**\n * @dev Returns the uint16 value for a given commitmentId from the commitmentPoolOracleLtvRatio mapping.\n * @param commitmentId The key to access the mapping.\n * @return The uint16 value for the specified commitmentId.\n */\n function getCommitmentPoolOracleLtvRatio(uint256 commitmentId)\n public\n view\n returns (uint16)\n {\n return commitmentPoolOracleLtvRatio[commitmentId];\n }\n\n // ---- TWAP\n\n function getUniswapV3PoolAddress(\n address _principalTokenAddress,\n address _collateralTokenAddress,\n uint24 _uniswapPoolFee\n ) public view returns (address) {\n return\n IUniswapV3Factory(UNISWAP_V3_FACTORY).getPool(\n _principalTokenAddress,\n _collateralTokenAddress,\n _uniswapPoolFee\n );\n }\n\n /*\n \n This returns a price ratio which to be normalized, must be divided by STANDARD_EXPANSION_FACTOR\n\n */\n\n function getUniswapPriceRatioForPoolRoutes(\n PoolRouteConfig[] memory poolRoutes\n ) public view returns (uint256 priceRatio) {\n require(poolRoutes.length <= 2, \"invalid pool routes length\");\n\n if (poolRoutes.length == 2) {\n uint256 pool0PriceRatio = getUniswapPriceRatioForPool(\n poolRoutes[0]\n );\n\n uint256 pool1PriceRatio = getUniswapPriceRatioForPool(\n poolRoutes[1]\n );\n\n return\n FullMath.mulDiv(\n pool0PriceRatio,\n pool1PriceRatio,\n STANDARD_EXPANSION_FACTOR\n );\n } else if (poolRoutes.length == 1) {\n return getUniswapPriceRatioForPool(poolRoutes[0]);\n }\n\n //else return 0\n }\n\n /*\n The resultant product is expanded by STANDARD_EXPANSION_FACTOR one time \n */\n function getUniswapPriceRatioForPool(\n PoolRouteConfig memory _poolRouteConfig\n ) public view returns (uint256 priceRatio) {\n uint160 sqrtPriceX96 = getSqrtTwapX96(\n _poolRouteConfig.pool,\n _poolRouteConfig.twapInterval\n );\n\n //This is the token 1 per token 0 price\n uint256 sqrtPrice = FullMath.mulDiv(\n sqrtPriceX96,\n STANDARD_EXPANSION_FACTOR,\n 2**96\n );\n\n uint256 sqrtPriceInverse = (STANDARD_EXPANSION_FACTOR *\n STANDARD_EXPANSION_FACTOR) / sqrtPrice;\n\n uint256 price = _poolRouteConfig.zeroForOne\n ? sqrtPrice * sqrtPrice\n : sqrtPriceInverse * sqrtPriceInverse;\n\n return price / STANDARD_EXPANSION_FACTOR;\n }\n\n function getSqrtTwapX96(address uniswapV3Pool, uint32 twapInterval)\n internal\n view\n returns (uint160 sqrtPriceX96)\n {\n if (twapInterval == 0) {\n // return the current price if twapInterval == 0\n (sqrtPriceX96, , , , , , ) = IUniswapV3Pool(uniswapV3Pool).slot0();\n } else {\n uint32[] memory secondsAgos = new uint32[](2);\n secondsAgos[0] = twapInterval + 1; // from (before)\n secondsAgos[1] = 1; // one block prior\n\n (int56[] memory tickCumulatives, ) = IUniswapV3Pool(uniswapV3Pool)\n .observe(secondsAgos);\n\n // tick(imprecise as it's an integer) to price\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(\n int24(\n (tickCumulatives[1] - tickCumulatives[0]) /\n int32(twapInterval)\n )\n );\n }\n }\n\n function getPriceX96FromSqrtPriceX96(uint160 sqrtPriceX96)\n internal\n pure\n returns (uint256 priceX96)\n {\n return FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96);\n }\n\n // -----\n\n /**\n * @notice Return the array of borrowers that are allowlisted for a commitment\n * @param _commitmentId The commitment id for the commitment to query.\n * @return borrowers_ An array of addresses restricted to accept the commitment. Empty array means unrestricted.\n */\n function getCommitmentBorrowers(uint256 _commitmentId)\n external\n view\n returns (address[] memory borrowers_)\n {\n borrowers_ = commitmentBorrowersList[_commitmentId].values();\n }\n\n /**\n * @notice Return the collateral type based on the commitmentcollateral type. Collateral type is used in the base lending protocol.\n * @param _type The type of collateral to be used for the loan.\n */\n function _getEscrowCollateralType(CommitmentCollateralType _type)\n internal\n pure\n returns (CollateralType)\n {\n if (_type == CommitmentCollateralType.ERC20) {\n return CollateralType.ERC20;\n }\n if (\n _type == CommitmentCollateralType.ERC721 ||\n _type == CommitmentCollateralType.ERC721_ANY_ID ||\n _type == CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n return CollateralType.ERC721;\n }\n if (\n _type == CommitmentCollateralType.ERC1155 ||\n _type == CommitmentCollateralType.ERC1155_ANY_ID ||\n _type == CommitmentCollateralType.ERC1155_MERKLE_PROOF\n ) {\n return CollateralType.ERC1155;\n }\n\n revert(\"Unknown Collateral Type\");\n }\n\n function getCommitmentMarketId(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitments[_commitmentId].marketId;\n }\n\n function getCommitmentLender(uint256 _commitmentId)\n external\n view\n returns (address)\n {\n return commitments[_commitmentId].lender;\n }\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitmentPrincipalAccepted[_commitmentId];\n }\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n external\n view\n returns (uint256)\n {\n return commitments[_commitmentId].maxPrincipal;\n }\n\n function getCommitmentPrincipalTokenAddress(uint256 _commitmentId)\n external\n view\n returns (address)\n {\n return commitments[_commitmentId].principalTokenAddress;\n }\n\n function getCommitmentCollateralTokenAddress(uint256 _commitmentId)\n external\n view\n returns (address)\n {\n return commitments[_commitmentId].collateralTokenAddress;\n }\n\n\n\n //Overrides\n function _msgSender()\n internal\n view\n virtual\n override(ContextUpgradeable, ExtensionsContextUpgradeable)\n returns (address sender)\n {\n return ExtensionsContextUpgradeable._msgSender();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarder.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"./LenderCommitmentForwarder_G1.sol\";\n\ncontract LenderCommitmentForwarder is LenderCommitmentForwarder_G1 {\n constructor(address _tellerV2, address _marketRegistry)\n LenderCommitmentForwarder_G1(_tellerV2, _marketRegistry)\n {\n _disableInitializers();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarderAlpha.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"./LenderCommitmentForwarder_U1.sol\";\n\ncontract LenderCommitmentForwarderAlpha is LenderCommitmentForwarder_U1 {\n constructor(\n address _tellerV2,\n address _marketRegistry,\n address _uniswapV3Factory\n )\n LenderCommitmentForwarder_U1(\n _tellerV2,\n _marketRegistry,\n _uniswapV3Factory\n )\n {\n // we only want this on an proxy deployment so it only affects the impl\n _disableInitializers();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LenderCommitmentForwarderStaging.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"./LenderCommitmentForwarder_G3.sol\";\n\ncontract LenderCommitmentForwarderStaging is\n ILenderCommitmentForwarder,\n LenderCommitmentForwarder_G3\n{\n constructor(address _tellerV2, address _marketRegistry)\n LenderCommitmentForwarder_G3(_tellerV2, _marketRegistry)\n {\n // we only want this on an proxy deployment so it only affects the impl\n _disableInitializers();\n }\n}\n" + }, + "contracts/LenderCommitmentForwarder/LoanReferralForwarder.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n// Interfaces\nimport \"../interfaces/ITellerV2.sol\";\nimport \"../interfaces/IProtocolFee.sol\";\nimport \"../interfaces/ITellerV2Storage.sol\";\nimport \"../interfaces/IMarketRegistry.sol\"; \nimport \"../interfaces/ISmartCommitment.sol\";\nimport \"../interfaces/ISmartCommitmentForwarder.sol\";\nimport \"../interfaces/IFlashRolloverLoan_G4.sol\";\nimport \"../libraries/NumbersLib.sol\";\n\nimport { ILenderCommitmentForwarder } from \"../interfaces/ILenderCommitmentForwarder.sol\";\n \nimport { ILenderCommitmentForwarder_U1 } from \"../interfaces/ILenderCommitmentForwarder_U1.sol\";\n\n\n\n\ncontract LoanReferralForwarder \n {\n using AddressUpgradeable for address;\n using NumbersLib for uint256;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITellerV2 public immutable TELLER_V2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n \n \n\n struct AcceptCommitmentArgs {\n uint256 commitmentId;\n address smartCommitmentAddress; //if this is not address(0), we will use this ! leave empty if not used. \n uint256 principalAmount;\n uint256 collateralAmount;\n uint256 collateralTokenId;\n address collateralTokenAddress;\n uint16 interestRate;\n uint32 loanDuration;\n bytes32[] merkleProof; //empty array if not used\n }\n\n\n /**\n *\n * @notice Initializes the FlashRolloverLoan with necessary contract addresses.\n *\n * @dev Using a custom OpenZeppelin upgrades tag. Ensure the constructor logic is safe for upgrades.\n *\n * @param _tellerV2 The address of the TellerV2 contract.\n \n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _tellerV2 \n \n ) {\n TELLER_V2 = ITellerV2(_tellerV2);\n \n }\n\n \n\n /*\n \n */\n function acceptCommitmentWithReferral(\n address _commitmentForwarder, //leave 0 if using smart commitment address\n \n \n AcceptCommitmentArgs calldata _acceptCommitmentArgs ,\n \n \n address _recipient,\n uint256 _reward,\n address _rewardRecipient\n\n ) external returns (uint256 bidId_) {\n\n \n address principalTokenAddress = address(0);\n uint256 balanceBefore;\n\n \n require(_reward <= _acceptCommitmentArgs.principalAmount / 10, \"Reward can be no more than 10% of principal\");\n\n if (_acceptCommitmentArgs.smartCommitmentAddress != address(0)) {\n\n \n principalTokenAddress = ISmartCommitment(_acceptCommitmentArgs.smartCommitmentAddress).getPrincipalTokenAddress ();\n \n // Accept commitment and receive funds to this contract\n balanceBefore = IERC20(principalTokenAddress).balanceOf(address(this));\n \n bidId_ = _acceptSmartCommitmentWithRecipient(\n _commitmentForwarder,\n _acceptCommitmentArgs\n\n );\n\n \n }else{ \n principalTokenAddress = ILenderCommitmentForwarder_U1(_commitmentForwarder)\n .getCommitmentPrincipalTokenAddress (_acceptCommitmentArgs.commitmentId);\n \n // Accept commitment and receive funds to this contract\n balanceBefore = IERC20(principalTokenAddress).balanceOf(address(this));\n \n\n bidId_ = _acceptCommitmentWithRecipient(\n _commitmentForwarder,\n _acceptCommitmentArgs\n\n ); \n\n\n\n }\n \n uint256 balanceAfter = IERC20(principalTokenAddress).balanceOf(address(this));\n\n uint256 fundsRemaining = balanceAfter - balanceBefore;\n\n // require( fundsRemaining >= _minAmountReceived, \"Insufficient funds received\" );\n\n \n IERC20Upgradeable(principalTokenAddress).transfer(\n _rewardRecipient,\n _reward\n );\n\n IERC20Upgradeable(principalTokenAddress).transfer(\n _recipient,\n fundsRemaining - _reward\n );\n\n\n\n \n }\n\n\n function _acceptSmartCommitmentWithRecipient( \n address _smartCommitmentForwarder,\n AcceptCommitmentArgs calldata _acceptCommitmentArgs \n \n\n ) internal returns (uint256 bidId_) {\n\n bytes memory responseData = address(_smartCommitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ISmartCommitmentForwarder\n .acceptSmartCommitmentWithRecipient\n .selector,\n _acceptCommitmentArgs.smartCommitmentAddress,\n _acceptCommitmentArgs.principalAmount,\n _acceptCommitmentArgs.collateralAmount,\n _acceptCommitmentArgs.collateralTokenId,\n _acceptCommitmentArgs.collateralTokenAddress,\n address(this),\n _acceptCommitmentArgs.interestRate,\n _acceptCommitmentArgs.loanDuration\n ),\n msg.sender // borrower \n )\n );\n\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n\n\n }\n\n\n\n function _acceptCommitmentWithRecipient(\n address _commitmentForwarder,\n AcceptCommitmentArgs calldata _acceptCommitmentArgs \n \n\n ) internal returns (uint256 bidId_) {\n\n bytes memory responseData = address(_commitmentForwarder)\n .functionCall(\n abi.encodePacked(\n abi.encodeWithSelector(\n ILenderCommitmentForwarder\n .acceptCommitmentWithRecipient\n .selector,\n _acceptCommitmentArgs.commitmentId,\n _acceptCommitmentArgs.principalAmount,\n _acceptCommitmentArgs.collateralAmount,\n _acceptCommitmentArgs.collateralTokenId,\n _acceptCommitmentArgs.collateralTokenAddress,\n address(this),\n _acceptCommitmentArgs.interestRate,\n _acceptCommitmentArgs.loanDuration\n ),\n msg.sender //borrower \n )\n );\n\n (bidId_) = abi.decode(responseData, (uint256));\n\n\n }\n\n \n /**\n * @notice Fetches the protocol fee percentage from the Teller V2 protocol.\n * @return The protocol fee percentage as defined in the Teller V2 protocol.\n */\n function _getProtocolFeePct() internal view returns (uint16) {\n return IProtocolFee(address(TELLER_V2)).protocolFee();\n }\n}" + }, + "contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../TellerV2MarketForwarder_G3.sol\";\nimport \"./extensions/ExtensionsContextUpgradeable.sol\";\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\nimport \"../interfaces/ISmartCommitmentForwarder.sol\";\nimport \"./LenderCommitmentForwarder_G1.sol\";\n\nimport \"../interfaces/IPausableTimestamp.sol\";\n\nimport \"../interfaces/IHasProtocolPausingManager.sol\";\n\nimport \"../interfaces/IProtocolPausingManager.sol\";\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\n\n\nimport { CommitmentCollateralType, ISmartCommitment } from \"../interfaces/ISmartCommitment.sol\";\n\n \ncontract SmartCommitmentForwarder is\n ExtensionsContextUpgradeable, //this should always be first for upgradeability\n TellerV2MarketForwarder_G3,\n PausableUpgradeable, //this does add some storage but AFTER all other storage\n ISmartCommitmentForwarder,\n IPausableTimestamp\n {\n\n using MathUpgradeable for uint256;\n\n event ExercisedSmartCommitment(\n address indexed smartCommitmentAddress,\n address borrower,\n uint256 tokenAmount,\n uint256 bidId\n );\n\n error InsufficientBorrowerCollateral(uint256 required, uint256 actual);\n\n\n\n modifier onlyProtocolPauser() { \n\n address pausingManager = IHasProtocolPausingManager( _tellerV2 ).getProtocolPausingManager();\n require( IProtocolPausingManager( pausingManager ).isPauser(_msgSender()) , \"Sender not authorized\");\n _;\n }\n\n\n modifier onlyProtocolOwner() { \n require( Ownable( _tellerV2 ).owner() == _msgSender() , \"Sender not authorized\");\n _;\n }\n\n uint256 public liquidationProtocolFeePercent; \n uint256 internal lastUnpausedAt;\n\n\n constructor(address _protocolAddress, address _marketRegistry)\n TellerV2MarketForwarder_G3(_protocolAddress, _marketRegistry)\n { }\n\n function initialize() public initializer { \n __Pausable_init();\n }\n\n function setLiquidationProtocolFeePercent(uint256 _percent) \n public onlyProtocolOwner { \n //max is 100% \n require( _percent <= 10000 , \"invalid fee percent\" );\n liquidationProtocolFeePercent = _percent;\n }\n\n function getLiquidationProtocolFeePercent() \n public view returns (uint256){ \n return liquidationProtocolFeePercent ;\n }\n\n /**\n * @notice Accept the commitment to submitBid and acceptBid using the funds\n * @dev LoanDuration must be longer than the market payment cycle\n * @param _smartCommitmentAddress The address of the smart commitment contract.\n * @param _principalAmount The amount of currency to borrow for the loan.\n * @param _collateralAmount The amount of collateral to use for the loan.\n * @param _collateralTokenId The tokenId of collateral to use for the loan if ERC721 or ERC1155.\n * @param _collateralTokenAddress The contract address to use for the loan collateral tokens.\n * @param _recipient The address to receive the loan funds.\n * @param _interestRate The interest rate APY to use for the loan in basis points.\n * @param _loanDuration The overall duration for the loan. Must be longer than market payment cycle duration.\n * @return bidId The ID of the loan that was created on TellerV2\n */\n function acceptSmartCommitmentWithRecipient(\n address _smartCommitmentAddress,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public whenNotPaused returns (uint256 bidId) {\n require(\n ISmartCommitment(_smartCommitmentAddress)\n .getCollateralTokenType() <=\n CommitmentCollateralType.ERC1155_ANY_ID,\n \"Invalid commitment collateral type\"\n );\n\n return\n _acceptCommitment(\n _smartCommitmentAddress,\n _principalAmount,\n _collateralAmount,\n _collateralTokenId,\n _collateralTokenAddress,\n _recipient,\n _interestRate,\n _loanDuration\n );\n }\n\n function _acceptCommitment(\n address _smartCommitmentAddress,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) internal returns (uint256 bidId) {\n ISmartCommitment _commitment = ISmartCommitment(\n _smartCommitmentAddress\n );\n\n CreateLoanArgs memory createLoanArgs;\n\n createLoanArgs.marketId = _commitment.getMarketId();\n createLoanArgs.lendingToken = _commitment.getPrincipalTokenAddress();\n createLoanArgs.principal = _principalAmount;\n createLoanArgs.duration = _loanDuration;\n createLoanArgs.interestRate = _interestRate;\n createLoanArgs.recipient = _recipient;\n\n CommitmentCollateralType commitmentCollateralTokenType = _commitment\n .getCollateralTokenType();\n\n if (commitmentCollateralTokenType != CommitmentCollateralType.NONE) {\n createLoanArgs.collateral = new Collateral[](1);\n createLoanArgs.collateral[0] = Collateral({\n _collateralType: _getEscrowCollateralType(\n commitmentCollateralTokenType\n ),\n _tokenId: _collateralTokenId,\n _amount: _collateralAmount,\n _collateralAddress: _collateralTokenAddress // commitment.collateralTokenAddress\n });\n }\n\n bidId = _submitBidWithCollateral(createLoanArgs, _msgSender());\n\n _commitment.acceptFundsForAcceptBid(\n _msgSender(), //borrower\n bidId,\n _principalAmount,\n _collateralAmount,\n _collateralTokenAddress,\n _collateralTokenId,\n _loanDuration,\n _interestRate\n );\n\n emit ExercisedSmartCommitment(\n _smartCommitmentAddress,\n _msgSender(),\n _principalAmount,\n bidId\n );\n }\n\n /**\n * @notice Return the collateral type based on the commitmentcollateral type. Collateral type is used in the base lending protocol.\n * @param _type The type of collateral to be used for the loan.\n */\n function _getEscrowCollateralType(CommitmentCollateralType _type)\n internal\n pure\n returns (CollateralType)\n {\n if (_type == CommitmentCollateralType.ERC20) {\n return CollateralType.ERC20;\n }\n if (\n _type == CommitmentCollateralType.ERC721 ||\n _type == CommitmentCollateralType.ERC721_ANY_ID ||\n _type == CommitmentCollateralType.ERC721_MERKLE_PROOF\n ) {\n return CollateralType.ERC721;\n }\n if (\n _type == CommitmentCollateralType.ERC1155 ||\n _type == CommitmentCollateralType.ERC1155_ANY_ID ||\n _type == CommitmentCollateralType.ERC1155_MERKLE_PROOF\n ) {\n return CollateralType.ERC1155;\n }\n\n revert(\"Unknown Collateral Type\");\n }\n\n\n\n /**\n * @notice Lets the DAO/owner of the protocol implement an emergency stop mechanism.\n */\n function pause() public virtual onlyProtocolPauser whenNotPaused {\n _pause();\n }\n\n /**\n * @notice Lets the DAO/owner of the protocol undo a previously implemented emergency stop.\n */\n function unpause() public virtual onlyProtocolPauser whenPaused {\n setLastUnpausedAt();\n _unpause();\n }\n\n\n function getLastUnpausedAt() \n public view \n returns (uint256) {\n\n\n address pausingManager = IHasProtocolPausingManager( _tellerV2 ).getProtocolPausingManager();\n \n return MathUpgradeable.max(\n lastUnpausedAt,\n IPausableTimestamp(pausingManager).getLastUnpausedAt()\n )\n ;\n \n\n }\n\n\n function setLastUnpausedAt() internal {\n lastUnpausedAt = block.timestamp;\n }\n\n\n // -----\n\n //Overrides\n function _msgSender()\n internal\n view\n virtual\n override(ContextUpgradeable, ExtensionsContextUpgradeable)\n returns (address sender)\n {\n return ExtensionsContextUpgradeable._msgSender();\n }\n \n}\n" + }, + "contracts/LenderManager.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\";\n\n// Interfaces\nimport \"./interfaces/ILenderManager.sol\";\nimport \"./interfaces/ITellerV2.sol\";\nimport \"./interfaces/IMarketRegistry.sol\";\n\ncontract LenderManager is\n Initializable,\n OwnableUpgradeable,\n ERC721Upgradeable,\n ILenderManager\n{\n IMarketRegistry public immutable marketRegistry;\n\n constructor(IMarketRegistry _marketRegistry) {\n marketRegistry = _marketRegistry;\n }\n\n function initialize() external initializer {\n __LenderManager_init();\n }\n\n function __LenderManager_init() internal onlyInitializing {\n __Ownable_init();\n __ERC721_init(\"TellerLoan\", \"TLN\");\n }\n\n /**\n * @notice Registers a new active lender for a loan, minting the nft\n * @param _bidId The id for the loan to set.\n * @param _newLender The address of the new active lender.\n */\n function registerLoan(uint256 _bidId, address _newLender)\n public\n override\n onlyOwner\n {\n _safeMint(_newLender, _bidId, \"\");\n }\n\n /**\n * @notice Returns the address of the lender that owns a given loan/bid.\n * @param _bidId The id of the bid of which to return the market id\n */\n function _getLoanMarketId(uint256 _bidId) internal view returns (uint256) {\n return ITellerV2(owner()).getLoanMarketId(_bidId);\n }\n\n /**\n * @notice Returns the verification status of a lender for a market.\n * @param _lender The address of the lender which should be verified by the market\n * @param _bidId The id of the bid of which to return the market id\n */\n function _hasMarketVerification(address _lender, uint256 _bidId)\n internal\n view\n virtual\n returns (bool isVerified_)\n {\n uint256 _marketId = _getLoanMarketId(_bidId);\n\n (isVerified_, ) = marketRegistry.isVerifiedLender(_marketId, _lender);\n }\n\n /** ERC721 Functions **/\n\n function _beforeTokenTransfer(address, address to, uint256 tokenId, uint256)\n internal\n override\n {\n require(_hasMarketVerification(to, tokenId), \"Not approved by market\");\n }\n\n function _baseURI() internal view override returns (string memory) {\n return \"\";\n }\n}\n" + }, + "contracts/libraries/DateTimeLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\n// ----------------------------------------------------------------------------\n// BokkyPooBah's DateTime Library v1.01\n//\n// A gas-efficient Solidity date and time library\n//\n// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\n//\n// Tested date range 1970/01/01 to 2345/12/31\n//\n// Conventions:\n// Unit | Range | Notes\n// :-------- |:-------------:|:-----\n// timestamp | >= 0 | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC\n// year | 1970 ... 2345 |\n// month | 1 ... 12 |\n// day | 1 ... 31 |\n// hour | 0 ... 23 |\n// minute | 0 ... 59 |\n// second | 0 ... 59 |\n// dayOfWeek | 1 ... 7 | 1 = Monday, ..., 7 = Sunday\n//\n//\n// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.\n// ----------------------------------------------------------------------------\n\nlibrary BokkyPooBahsDateTimeLibrary {\n uint constant SECONDS_PER_DAY = 24 * 60 * 60;\n uint constant SECONDS_PER_HOUR = 60 * 60;\n uint constant SECONDS_PER_MINUTE = 60;\n int constant OFFSET19700101 = 2440588;\n\n uint constant DOW_MON = 1;\n uint constant DOW_TUE = 2;\n uint constant DOW_WED = 3;\n uint constant DOW_THU = 4;\n uint constant DOW_FRI = 5;\n uint constant DOW_SAT = 6;\n uint constant DOW_SUN = 7;\n\n // ------------------------------------------------------------------------\n // Calculate the number of days from 1970/01/01 to year/month/day using\n // the date conversion algorithm from\n // https://aa.usno.navy.mil/faq/JD_formula.html\n // and subtracting the offset 2440588 so that 1970/01/01 is day 0\n //\n // days = day\n // - 32075\n // + 1461 * (year + 4800 + (month - 14) / 12) / 4\n // + 367 * (month - 2 - (month - 14) / 12 * 12) / 12\n // - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4\n // - offset\n // ------------------------------------------------------------------------\n function _daysFromDate(uint year, uint month, uint day)\n internal\n pure\n returns (uint _days)\n {\n require(year >= 1970);\n int _year = int(year);\n int _month = int(month);\n int _day = int(day);\n\n int __days = _day -\n 32075 +\n (1461 * (_year + 4800 + (_month - 14) / 12)) /\n 4 +\n (367 * (_month - 2 - ((_month - 14) / 12) * 12)) /\n 12 -\n (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /\n 4 -\n OFFSET19700101;\n\n _days = uint(__days);\n }\n\n // ------------------------------------------------------------------------\n // Calculate year/month/day from the number of days since 1970/01/01 using\n // the date conversion algorithm from\n // http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n // and adding the offset 2440588 so that 1970/01/01 is day 0\n //\n // int L = days + 68569 + offset\n // int N = 4 * L / 146097\n // L = L - (146097 * N + 3) / 4\n // year = 4000 * (L + 1) / 1461001\n // L = L - 1461 * year / 4 + 31\n // month = 80 * L / 2447\n // dd = L - 2447 * month / 80\n // L = month / 11\n // month = month + 2 - 12 * L\n // year = 100 * (N - 49) + year + L\n // ------------------------------------------------------------------------\n function _daysToDate(uint _days)\n internal\n pure\n returns (uint year, uint month, uint day)\n {\n int __days = int(_days);\n\n int L = __days + 68569 + OFFSET19700101;\n int N = (4 * L) / 146097;\n L = L - (146097 * N + 3) / 4;\n int _year = (4000 * (L + 1)) / 1461001;\n L = L - (1461 * _year) / 4 + 31;\n int _month = (80 * L) / 2447;\n int _day = L - (2447 * _month) / 80;\n L = _month / 11;\n _month = _month + 2 - 12 * L;\n _year = 100 * (N - 49) + _year + L;\n\n year = uint(_year);\n month = uint(_month);\n day = uint(_day);\n }\n\n function timestampFromDate(uint year, uint month, uint day)\n internal\n pure\n returns (uint timestamp)\n {\n timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;\n }\n\n function timestampFromDateTime(\n uint year,\n uint month,\n uint day,\n uint hour,\n uint minute,\n uint second\n ) internal pure returns (uint timestamp) {\n timestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n hour *\n SECONDS_PER_HOUR +\n minute *\n SECONDS_PER_MINUTE +\n second;\n }\n\n function timestampToDate(uint timestamp)\n internal\n pure\n returns (uint year, uint month, uint day)\n {\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n\n function timestampToDateTime(uint timestamp)\n internal\n pure\n returns (\n uint year,\n uint month,\n uint day,\n uint hour,\n uint minute,\n uint second\n )\n {\n (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n uint secs = timestamp % SECONDS_PER_DAY;\n hour = secs / SECONDS_PER_HOUR;\n secs = secs % SECONDS_PER_HOUR;\n minute = secs / SECONDS_PER_MINUTE;\n second = secs % SECONDS_PER_MINUTE;\n }\n\n function isValidDate(uint year, uint month, uint day)\n internal\n pure\n returns (bool valid)\n {\n if (year >= 1970 && month > 0 && month <= 12) {\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > 0 && day <= daysInMonth) {\n valid = true;\n }\n }\n }\n\n function isValidDateTime(\n uint year,\n uint month,\n uint day,\n uint hour,\n uint minute,\n uint second\n ) internal pure returns (bool valid) {\n if (isValidDate(year, month, day)) {\n if (hour < 24 && minute < 60 && second < 60) {\n valid = true;\n }\n }\n }\n\n function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {\n (uint year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);\n leapYear = _isLeapYear(year);\n }\n\n function _isLeapYear(uint year) internal pure returns (bool leapYear) {\n leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);\n }\n\n function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {\n weekDay = getDayOfWeek(timestamp) <= DOW_FRI;\n }\n\n function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {\n weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;\n }\n\n function getDaysInMonth(uint timestamp)\n internal\n pure\n returns (uint daysInMonth)\n {\n (uint year, uint month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);\n daysInMonth = _getDaysInMonth(year, month);\n }\n\n function _getDaysInMonth(uint year, uint month)\n internal\n pure\n returns (uint daysInMonth)\n {\n if (\n month == 1 ||\n month == 3 ||\n month == 5 ||\n month == 7 ||\n month == 8 ||\n month == 10 ||\n month == 12\n ) {\n daysInMonth = 31;\n } else if (month != 2) {\n daysInMonth = 30;\n } else {\n daysInMonth = _isLeapYear(year) ? 29 : 28;\n }\n }\n\n // 1 = Monday, 7 = Sunday\n function getDayOfWeek(uint timestamp)\n internal\n pure\n returns (uint dayOfWeek)\n {\n uint _days = timestamp / SECONDS_PER_DAY;\n dayOfWeek = ((_days + 3) % 7) + 1;\n }\n\n function getYear(uint timestamp) internal pure returns (uint year) {\n (year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n\n function getMonth(uint timestamp) internal pure returns (uint month) {\n (, month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n\n function getDay(uint timestamp) internal pure returns (uint day) {\n (, , day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n }\n\n function getHour(uint timestamp) internal pure returns (uint hour) {\n uint secs = timestamp % SECONDS_PER_DAY;\n hour = secs / SECONDS_PER_HOUR;\n }\n\n function getMinute(uint timestamp) internal pure returns (uint minute) {\n uint secs = timestamp % SECONDS_PER_HOUR;\n minute = secs / SECONDS_PER_MINUTE;\n }\n\n function getSecond(uint timestamp) internal pure returns (uint second) {\n second = timestamp % SECONDS_PER_MINUTE;\n }\n\n function addYears(uint timestamp, uint _years)\n internal\n pure\n returns (uint newTimestamp)\n {\n (uint year, uint month, uint day) = _daysToDate(\n timestamp / SECONDS_PER_DAY\n );\n year += _years;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n (timestamp % SECONDS_PER_DAY);\n require(newTimestamp >= timestamp);\n }\n\n function addMonths(uint timestamp, uint _months)\n internal\n pure\n returns (uint newTimestamp)\n {\n (uint year, uint month, uint day) = _daysToDate(\n timestamp / SECONDS_PER_DAY\n );\n month += _months;\n year += (month - 1) / 12;\n month = ((month - 1) % 12) + 1;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n (timestamp % SECONDS_PER_DAY);\n require(newTimestamp >= timestamp);\n }\n\n function addDays(uint timestamp, uint _days)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp + _days * SECONDS_PER_DAY;\n require(newTimestamp >= timestamp);\n }\n\n function addHours(uint timestamp, uint _hours)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;\n require(newTimestamp >= timestamp);\n }\n\n function addMinutes(uint timestamp, uint _minutes)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;\n require(newTimestamp >= timestamp);\n }\n\n function addSeconds(uint timestamp, uint _seconds)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp + _seconds;\n require(newTimestamp >= timestamp);\n }\n\n function subYears(uint timestamp, uint _years)\n internal\n pure\n returns (uint newTimestamp)\n {\n (uint year, uint month, uint day) = _daysToDate(\n timestamp / SECONDS_PER_DAY\n );\n year -= _years;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n (timestamp % SECONDS_PER_DAY);\n require(newTimestamp <= timestamp);\n }\n\n function subMonths(uint timestamp, uint _months)\n internal\n pure\n returns (uint newTimestamp)\n {\n (uint year, uint month, uint day) = _daysToDate(\n timestamp / SECONDS_PER_DAY\n );\n uint yearMonth = year * 12 + (month - 1) - _months;\n year = yearMonth / 12;\n month = (yearMonth % 12) + 1;\n uint daysInMonth = _getDaysInMonth(year, month);\n if (day > daysInMonth) {\n day = daysInMonth;\n }\n newTimestamp =\n _daysFromDate(year, month, day) *\n SECONDS_PER_DAY +\n (timestamp % SECONDS_PER_DAY);\n require(newTimestamp <= timestamp);\n }\n\n function subDays(uint timestamp, uint _days)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp - _days * SECONDS_PER_DAY;\n require(newTimestamp <= timestamp);\n }\n\n function subHours(uint timestamp, uint _hours)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;\n require(newTimestamp <= timestamp);\n }\n\n function subMinutes(uint timestamp, uint _minutes)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;\n require(newTimestamp <= timestamp);\n }\n\n function subSeconds(uint timestamp, uint _seconds)\n internal\n pure\n returns (uint newTimestamp)\n {\n newTimestamp = timestamp - _seconds;\n require(newTimestamp <= timestamp);\n }\n\n function diffYears(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _years)\n {\n require(fromTimestamp <= toTimestamp);\n (uint fromYear, , ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\n (uint toYear, , ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\n _years = toYear - fromYear;\n }\n\n function diffMonths(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _months)\n {\n require(fromTimestamp <= toTimestamp);\n (uint fromYear, uint fromMonth, ) = _daysToDate(\n fromTimestamp / SECONDS_PER_DAY\n );\n (uint toYear, uint toMonth, ) = _daysToDate(\n toTimestamp / SECONDS_PER_DAY\n );\n _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;\n }\n\n function diffDays(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _days)\n {\n require(fromTimestamp <= toTimestamp);\n _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;\n }\n\n function diffHours(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _hours)\n {\n require(fromTimestamp <= toTimestamp);\n _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;\n }\n\n function diffMinutes(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _minutes)\n {\n require(fromTimestamp <= toTimestamp);\n _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;\n }\n\n function diffSeconds(uint fromTimestamp, uint toTimestamp)\n internal\n pure\n returns (uint _seconds)\n {\n require(fromTimestamp <= toTimestamp);\n _seconds = toTimestamp - fromTimestamp;\n }\n}\n" + }, + "contracts/libraries/NumbersLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Libraries\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"./WadRayMath.sol\";\n\n/**\n * @dev Utility library for uint256 numbers\n *\n * @author develop@teller.finance\n */\nlibrary NumbersLib {\n using WadRayMath for uint256;\n\n /**\n * @dev It represents 100% with 2 decimal places.\n */\n uint16 internal constant PCT_100 = 10000;\n\n function percentFactor(uint256 decimals) internal pure returns (uint256) {\n return 100 * (10**decimals);\n }\n\n /**\n * @notice Returns a percentage value of a number.\n * @param self The number to get a percentage of.\n * @param percentage The percentage value to calculate with 2 decimal places (10000 = 100%).\n */\n function percent(uint256 self, uint16 percentage)\n internal\n pure\n returns (uint256)\n {\n return percent(self, percentage, 2);\n }\n\n /**\n * @notice Returns a percentage value of a number.\n * @param self The number to get a percentage of.\n * @param percentage The percentage value to calculate with.\n * @param decimals The number of decimals the percentage value is in.\n */\n function percent(uint256 self, uint256 percentage, uint256 decimals)\n internal\n pure\n returns (uint256)\n {\n return (self * percentage) / percentFactor(decimals);\n }\n\n /**\n * @notice it returns the absolute number of a specified parameter\n * @param self the number to be returned in it's absolute\n * @return the absolute number\n */\n function abs(int256 self) internal pure returns (uint256) {\n return self >= 0 ? uint256(self) : uint256(-1 * self);\n }\n\n /**\n * @notice Returns a ratio percentage of {num1} to {num2}.\n * @dev Returned value is type uint16.\n * @param num1 The number used to get the ratio for.\n * @param num2 The number used to get the ratio from.\n * @return Ratio percentage with 2 decimal places (10000 = 100%).\n */\n function ratioOf(uint256 num1, uint256 num2)\n internal\n pure\n returns (uint16)\n {\n return SafeCast.toUint16(ratioOf(num1, num2, 2));\n }\n\n /**\n * @notice Returns a ratio percentage of {num1} to {num2}.\n * @param num1 The number used to get the ratio for.\n * @param num2 The number used to get the ratio from.\n * @param decimals The number of decimals the percentage value is returned in.\n * @return Ratio percentage value.\n */\n function ratioOf(uint256 num1, uint256 num2, uint256 decimals)\n internal\n pure\n returns (uint256)\n {\n if (num2 == 0) return 0;\n return (num1 * percentFactor(decimals)) / num2;\n }\n\n /**\n * @notice Calculates the payment amount for a cycle duration.\n * The formula is calculated based on the standard Estimated Monthly Installment (https://en.wikipedia.org/wiki/Equated_monthly_installment)\n * EMI = [P x R x (1+R)^N]/[(1+R)^N-1]\n * @param principal The starting amount that is owed on the loan.\n * @param loanDuration The length of the loan.\n * @param cycleDuration The length of the loan's payment cycle.\n * @param apr The annual percentage rate of the loan.\n */\n function pmt(\n uint256 principal,\n uint32 loanDuration,\n uint32 cycleDuration,\n uint16 apr,\n uint256 daysInYear\n ) internal pure returns (uint256) {\n require(\n loanDuration >= cycleDuration,\n \"PMT: cycle duration < loan duration\"\n );\n if (apr == 0)\n return\n Math.mulDiv(\n principal,\n cycleDuration,\n loanDuration,\n Math.Rounding.Up\n );\n\n // Number of payment cycles for the duration of the loan\n uint256 n = Math.ceilDiv(loanDuration, cycleDuration);\n\n uint256 one = WadRayMath.wad();\n uint256 r = WadRayMath.pctToWad(apr).wadMul(cycleDuration).wadDiv(\n daysInYear\n );\n uint256 exp = (one + r).wadPow(n);\n uint256 numerator = principal.wadMul(r).wadMul(exp);\n uint256 denominator = exp - one;\n\n return numerator.wadDiv(denominator);\n }\n}\n" + }, + "contracts/libraries/uniswap/FixedPoint96.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.4.0;\n\n/// @title FixedPoint96\n/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)\n/// @dev Used in SqrtPriceMath.sol\nlibrary FixedPoint96 {\n uint8 internal constant RESOLUTION = 96;\n uint256 internal constant Q96 = 0x1000000000000000000000000;\n}\n" + }, + "contracts/libraries/uniswap/FullMath.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title Contains 512-bit math functions\n/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision\n/// @dev Handles \"phantom overflow\" i.e., allows multiplication and division where an intermediate value overflows 256 bits\nlibrary FullMath {\n /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n /// @param a The multiplicand\n /// @param b The multiplier\n /// @param denominator The divisor\n /// @return result The 256-bit result\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv\n function mulDiv(uint256 a, uint256 b, uint256 denominator)\n internal\n pure\n returns (uint256 result)\n {\n // 512-bit multiply [prod1 prod0] = a * b\n // Compute the product mod 2**256 and mod 2**256 - 1\n // then use the Chinese Remainder Theorem to reconstruct\n // 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(a, b, not(0))\n prod0 := mul(a, b)\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 require(denominator > 0);\n assembly {\n result := div(prod0, denominator)\n }\n return result;\n }\n\n // Make sure the result is less than 2**256.\n // Also prevents denominator == 0\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0]\n // Compute remainder using mulmod\n uint256 remainder;\n assembly {\n remainder := mulmod(a, b, denominator)\n }\n // Subtract 256 bit number from 512 bit number\n assembly {\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator\n // Compute largest power of two divisor of denominator.\n // Always >= 1.\n // uint256 twos = -denominator & denominator;\n uint256 twos = (~denominator + 1) & denominator;\n // Divide denominator by power of two\n assembly {\n denominator := div(denominator, twos)\n }\n\n // Divide [prod1 prod0] by the factors of two\n assembly {\n prod0 := div(prod0, twos)\n }\n // Shift in bits from prod1 into prod0. For this we need\n // to flip `twos` such that it is 2**256 / twos.\n // If twos is zero, then it becomes one\n assembly {\n twos := add(div(sub(0, twos), twos), 1)\n }\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2**256\n // Now that denominator is an odd number, it has an inverse\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\n // Compute the inverse by starting with a seed that is correct\n // correct for four bits. That is, denominator * inv = 1 mod 2**4\n uint256 inv = (3 * denominator) ^ 2;\n // Now use Newton-Raphson iteration to improve the precision.\n // Thanks to Hensel's lifting lemma, this also works in modular\n // arithmetic, doubling the correct bits in each step.\n inv *= 2 - denominator * inv; // inverse mod 2**8\n inv *= 2 - denominator * inv; // inverse mod 2**16\n inv *= 2 - denominator * inv; // inverse mod 2**32\n inv *= 2 - denominator * inv; // inverse mod 2**64\n inv *= 2 - denominator * inv; // inverse mod 2**128\n inv *= 2 - denominator * inv; // inverse mod 2**256\n\n // Because the division is now exact we can divide by multiplying\n // with the modular inverse of denominator. This will give us the\n // correct result modulo 2**256. Since the precoditions guarantee\n // that the outcome is less than 2**256, this is the final result.\n // We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inv;\n return result;\n }\n\n /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n /// @param a The multiplicand\n /// @param b The multiplier\n /// @param denominator The divisor\n /// @return result The 256-bit result\n function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator)\n internal\n pure\n returns (uint256 result)\n {\n result = mulDiv(a, b, denominator);\n if (mulmod(a, b, denominator) > 0) {\n require(result < type(uint256).max);\n result++;\n }\n }\n}\n" + }, + "contracts/libraries/uniswap/TickMath.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.0;\n\n/// @title Math library for computing sqrt prices from ticks and vice versa\n/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports\n/// prices between 2**-128 and 2**128\nlibrary TickMath {\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128\n int24 internal constant MIN_TICK = -887272;\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128\n int24 internal constant MAX_TICK = -MIN_TICK;\n\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\n uint160 internal constant MAX_SQRT_RATIO =\n 1461446703485210103287273052203988822378723970342;\n\n /// @notice Calculates sqrt(1.0001^tick) * 2^96\n /// @dev Throws if |tick| > max tick\n /// @param tick The input tick for the above formula\n /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\n /// at the given tick\n function getSqrtRatioAtTick(int24 tick)\n internal\n pure\n returns (uint160 sqrtPriceX96)\n {\n uint256 absTick = tick < 0\n ? uint256(-int256(tick))\n : uint256(int256(tick));\n require(absTick <= uint256(uint24(MAX_TICK)), \"T\");\n\n uint256 ratio = absTick & 0x1 != 0\n ? 0xfffcb933bd6fad37aa2d162d1a594001\n : 0x100000000000000000000000000000000;\n if (absTick & 0x2 != 0)\n ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\n if (absTick & 0x4 != 0)\n ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\n if (absTick & 0x8 != 0)\n ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\n if (absTick & 0x10 != 0)\n ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\n if (absTick & 0x20 != 0)\n ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\n if (absTick & 0x40 != 0)\n ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\n if (absTick & 0x80 != 0)\n ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\n if (absTick & 0x100 != 0)\n ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\n if (absTick & 0x200 != 0)\n ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\n if (absTick & 0x400 != 0)\n ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\n if (absTick & 0x800 != 0)\n ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\n if (absTick & 0x1000 != 0)\n ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\n if (absTick & 0x2000 != 0)\n ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\n if (absTick & 0x4000 != 0)\n ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\n if (absTick & 0x8000 != 0)\n ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\n if (absTick & 0x10000 != 0)\n ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\n if (absTick & 0x20000 != 0)\n ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\n if (absTick & 0x40000 != 0)\n ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\n if (absTick & 0x80000 != 0)\n ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\n\n if (tick > 0) ratio = type(uint256).max / ratio;\n\n // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\n // we then downcast because we know the result always fits within 160 bits due to our tick input constraint\n // we round up in the division so getTickAtSqrtRatio of the output price is always consistent\n sqrtPriceX96 = uint160(\n (ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1)\n );\n }\n\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\n /// ever return.\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio\n function getTickAtSqrtRatio(uint160 sqrtPriceX96)\n internal\n pure\n returns (int24 tick)\n {\n // second inequality must be < because the price can never reach the price at the max tick\n require(\n sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO,\n \"R\"\n );\n uint256 ratio = uint256(sqrtPriceX96) << 32;\n\n uint256 r = ratio;\n uint256 msb = 0;\n\n assembly {\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(5, gt(r, 0xFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(4, gt(r, 0xFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(3, gt(r, 0xFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(2, gt(r, 0xF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(1, gt(r, 0x3))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := gt(r, 0x1)\n msb := or(msb, f)\n }\n\n if (msb >= 128) r = ratio >> (msb - 127);\n else r = ratio << (127 - msb);\n\n int256 log_2 = (int256(msb) - 128) << 64;\n\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(63, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(62, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(61, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(60, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(59, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(58, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(57, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(56, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(55, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(54, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(53, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(52, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(51, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(50, f))\n }\n\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number\n\n int24 tickLow = int24(\n (log_sqrt10001 - 3402992956809132418596140100660247210) >> 128\n );\n int24 tickHi = int24(\n (log_sqrt10001 + 291339464771989622907027621153398088495) >> 128\n );\n\n tick = tickLow == tickHi\n ? tickLow\n : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96\n ? tickHi\n : tickLow;\n }\n}\n" + }, + "contracts/libraries/UniswapPricingLibrary.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n \n\nimport {IUniswapPricingLibrary} from \"../interfaces/IUniswapPricingLibrary.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\n\n \nimport \"@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/MerkleProofUpgradeable.sol\";\n\nimport \"../interfaces/uniswap/IUniswapV3Pool.sol\"; \n\nimport \"../libraries/uniswap/TickMath.sol\";\nimport \"../libraries/uniswap/FixedPoint96.sol\";\nimport \"../libraries/uniswap/FullMath.sol\";\n \n \nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n\n/*\n\nOnly do decimal expansion if it is an ERC20 not anything else !! \n\n*/\n\nlibrary UniswapPricingLibrary \n{\n \n uint256 constant STANDARD_EXPANSION_FACTOR = 1e18;\n\n function getUniswapPriceRatioForPoolRoutes(\n IUniswapPricingLibrary.PoolRouteConfig[] memory poolRoutes\n ) public view returns (uint256 priceRatio) {\n require(poolRoutes.length <= 2, \"invalid pool routes length\");\n\n if (poolRoutes.length == 2) {\n uint256 pool0PriceRatio = getUniswapPriceRatioForPool(\n poolRoutes[0]\n );\n\n uint256 pool1PriceRatio = getUniswapPriceRatioForPool(\n poolRoutes[1]\n );\n\n return\n FullMath.mulDiv(\n pool0PriceRatio,\n pool1PriceRatio,\n STANDARD_EXPANSION_FACTOR\n );\n } else if (poolRoutes.length == 1) {\n return getUniswapPriceRatioForPool(poolRoutes[0]);\n }\n\n //else return 0\n }\n\n /*\n The resultant product is expanded by STANDARD_EXPANSION_FACTOR one time \n */\n function getUniswapPriceRatioForPool(\n IUniswapPricingLibrary.PoolRouteConfig memory _poolRouteConfig\n ) public view returns (uint256 priceRatio) {\n uint160 sqrtPriceX96 = getSqrtTwapX96(\n _poolRouteConfig.pool,\n _poolRouteConfig.twapInterval\n );\n\n //This is the token 1 per token 0 price\n uint256 sqrtPrice = FullMath.mulDiv(\n sqrtPriceX96,\n STANDARD_EXPANSION_FACTOR,\n 2**96\n );\n\n uint256 sqrtPriceInverse = (STANDARD_EXPANSION_FACTOR *\n STANDARD_EXPANSION_FACTOR) / sqrtPrice;\n\n uint256 price = _poolRouteConfig.zeroForOne\n ? sqrtPrice * sqrtPrice\n : sqrtPriceInverse * sqrtPriceInverse;\n\n return price / STANDARD_EXPANSION_FACTOR;\n }\n\n\n\n function getSqrtTwapX96(address uniswapV3Pool, uint32 twapInterval)\n internal\n view\n returns (uint160 sqrtPriceX96)\n {\n if (twapInterval == 0) {\n // return the current price if twapInterval == 0\n (sqrtPriceX96, , , , , , ) = IUniswapV3Pool(uniswapV3Pool).slot0();\n } else {\n uint32[] memory secondsAgos = new uint32[](2);\n secondsAgos[0] = twapInterval + 1; // from (before)\n secondsAgos[1] = 1; // one block prior\n\n (int56[] memory tickCumulatives, ) = IUniswapV3Pool(uniswapV3Pool)\n .observe(secondsAgos);\n\n // tick(imprecise as it's an integer) to price\n sqrtPriceX96 = TickMath.getSqrtRatioAtTick(\n int24(\n (tickCumulatives[1] - tickCumulatives[0]) /\n int32(twapInterval)\n )\n );\n }\n }\n\n function getPriceX96FromSqrtPriceX96(uint160 sqrtPriceX96)\n internal\n pure\n returns (uint256 priceX96)\n { \n\n \n return FullMath.mulDiv(sqrtPriceX96, sqrtPriceX96, FixedPoint96.Q96);\n }\n\n}" + }, + "contracts/libraries/V2Calculations.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n\n// SPDX-License-Identifier: MIT\n\n// Libraries\nimport \"./NumbersLib.sol\";\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { Bid } from \"../TellerV2Storage.sol\";\nimport { BokkyPooBahsDateTimeLibrary as BPBDTL } from \"./DateTimeLib.sol\";\n\nenum PaymentType {\n EMI,\n Bullet\n}\n\nenum PaymentCycleType {\n Seconds,\n Monthly\n}\n\nlibrary V2Calculations {\n using NumbersLib for uint256;\n\n /**\n * @notice Returns the timestamp of the last payment made for a loan.\n * @param _bid The loan bid struct to get the timestamp for.\n */\n function lastRepaidTimestamp(Bid storage _bid)\n internal\n view\n returns (uint32)\n {\n return\n _bid.loanDetails.lastRepaidTimestamp == 0\n ? _bid.loanDetails.acceptedTimestamp\n : _bid.loanDetails.lastRepaidTimestamp;\n }\n\n /**\n * @notice Calculates the amount owed for a loan.\n * @param _bid The loan bid struct to get the owed amount for.\n * @param _timestamp The timestamp at which to get the owed amount at.\n * @param _paymentCycleType The payment cycle type of the loan (Seconds or Monthly).\n */\n function calculateAmountOwed(\n Bid storage _bid,\n uint256 _timestamp,\n PaymentCycleType _paymentCycleType,\n uint32 _paymentCycleDuration\n )\n public\n view\n returns (\n uint256 owedPrincipal_,\n uint256 duePrincipal_,\n uint256 interest_\n )\n {\n // Total principal left to pay\n return\n calculateAmountOwed(\n _bid,\n lastRepaidTimestamp(_bid),\n _timestamp,\n _paymentCycleType,\n _paymentCycleDuration\n );\n }\n\n function calculateAmountOwed(\n Bid storage _bid,\n uint256 _lastRepaidTimestamp,\n uint256 _timestamp,\n PaymentCycleType _paymentCycleType,\n uint32 _paymentCycleDuration\n )\n public\n view\n returns (\n uint256 owedPrincipal_,\n uint256 duePrincipal_,\n uint256 interest_\n )\n {\n owedPrincipal_ =\n _bid.loanDetails.principal -\n _bid.loanDetails.totalRepaid.principal;\n\n uint256 owedTime = _timestamp - uint256(_lastRepaidTimestamp);\n\n {\n uint256 daysInYear = _paymentCycleType == PaymentCycleType.Monthly\n ? 360 days\n : 365 days;\n\n uint256 interestOwedInAYear = owedPrincipal_.percent(_bid.terms.APR, 2);\n \n interest_ = (interestOwedInAYear * owedTime) / daysInYear;\n }\n\n\n bool isLastPaymentCycle;\n {\n uint256 lastPaymentCycleDuration = _bid.loanDetails.loanDuration %\n _paymentCycleDuration;\n if (lastPaymentCycleDuration == 0) {\n lastPaymentCycleDuration = _paymentCycleDuration;\n }\n\n uint256 endDate = uint256(_bid.loanDetails.acceptedTimestamp) +\n uint256(_bid.loanDetails.loanDuration);\n uint256 lastPaymentCycleStart = endDate -\n uint256(lastPaymentCycleDuration);\n\n isLastPaymentCycle =\n uint256(_timestamp) > lastPaymentCycleStart ||\n owedPrincipal_ + interest_ <= _bid.terms.paymentCycleAmount;\n }\n\n if (_bid.paymentType == PaymentType.Bullet) {\n if (isLastPaymentCycle) {\n duePrincipal_ = owedPrincipal_;\n }\n } else {\n // Default to PaymentType.EMI\n // Max payable amount in a cycle\n // NOTE: the last cycle could have less than the calculated payment amount\n\n //the amount owed for the cycle should never exceed the current payment cycle amount so we use min here \n uint256 owedAmountForCycle = Math.min( ((_bid.terms.paymentCycleAmount * owedTime) ) /\n _paymentCycleDuration , _bid.terms.paymentCycleAmount+interest_ ) ;\n\n uint256 owedAmount = isLastPaymentCycle\n ? owedPrincipal_ + interest_\n : owedAmountForCycle ;\n\n duePrincipal_ = Math.min(owedAmount - interest_, owedPrincipal_);\n }\n }\n\n /**\n * @notice Calculates the amount owed for a loan for the next payment cycle.\n * @param _type The payment type of the loan.\n * @param _cycleType The cycle type set for the loan. (Seconds or Monthly)\n * @param _principal The starting amount that is owed on the loan.\n * @param _duration The length of the loan.\n * @param _paymentCycle The length of the loan's payment cycle.\n * @param _apr The annual percentage rate of the loan.\n */\n function calculatePaymentCycleAmount(\n PaymentType _type,\n PaymentCycleType _cycleType,\n uint256 _principal,\n uint32 _duration,\n uint32 _paymentCycle,\n uint16 _apr\n ) public view returns (uint256) {\n uint256 daysInYear = _cycleType == PaymentCycleType.Monthly\n ? 360 days\n : 365 days;\n if (_type == PaymentType.Bullet) {\n return\n _principal.percent(_apr).percent(\n uint256(_paymentCycle).ratioOf(daysInYear, 10),\n 10\n );\n }\n // Default to PaymentType.EMI\n return\n NumbersLib.pmt(\n _principal,\n _duration,\n _paymentCycle,\n _apr,\n daysInYear\n );\n }\n\n function calculateNextDueDate(\n uint32 _acceptedTimestamp,\n uint32 _paymentCycle,\n uint32 _loanDuration,\n uint32 _lastRepaidTimestamp,\n PaymentCycleType _bidPaymentCycleType\n ) public view returns (uint32 dueDate_) {\n // Calculate due date if payment cycle is set to monthly\n if (_bidPaymentCycleType == PaymentCycleType.Monthly) {\n // Calculate the cycle number the last repayment was made\n uint256 lastPaymentCycle = BPBDTL.diffMonths(\n _acceptedTimestamp,\n _lastRepaidTimestamp\n );\n if (\n BPBDTL.getDay(_lastRepaidTimestamp) >\n BPBDTL.getDay(_acceptedTimestamp)\n ) {\n lastPaymentCycle += 2;\n } else {\n lastPaymentCycle += 1;\n }\n\n dueDate_ = uint32(\n BPBDTL.addMonths(_acceptedTimestamp, lastPaymentCycle)\n );\n } else if (_bidPaymentCycleType == PaymentCycleType.Seconds) {\n // Start with the original due date being 1 payment cycle since bid was accepted\n dueDate_ = _acceptedTimestamp + _paymentCycle;\n // Calculate the cycle number the last repayment was made\n uint32 delta = _lastRepaidTimestamp - _acceptedTimestamp;\n if (delta > 0) {\n uint32 repaymentCycle = uint32(\n Math.ceilDiv(delta, _paymentCycle)\n );\n dueDate_ += (repaymentCycle * _paymentCycle);\n }\n }\n\n uint32 endOfLoan = _acceptedTimestamp + _loanDuration;\n //if we are in the last payment cycle, the next due date is the end of loan duration\n if (dueDate_ > endOfLoan) {\n dueDate_ = endOfLoan;\n }\n }\n}\n" + }, + "contracts/libraries/WadRayMath.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title WadRayMath library\n * @author Multiplier Finance\n * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits)\n */\nlibrary WadRayMath {\n using SafeMath for uint256;\n\n uint256 internal constant WAD = 1e18;\n uint256 internal constant halfWAD = WAD / 2;\n\n uint256 internal constant RAY = 1e27;\n uint256 internal constant halfRAY = RAY / 2;\n\n uint256 internal constant WAD_RAY_RATIO = 1e9;\n uint256 internal constant PCT_WAD_RATIO = 1e14;\n uint256 internal constant PCT_RAY_RATIO = 1e23;\n\n function ray() internal pure returns (uint256) {\n return RAY;\n }\n\n function wad() internal pure returns (uint256) {\n return WAD;\n }\n\n function halfRay() internal pure returns (uint256) {\n return halfRAY;\n }\n\n function halfWad() internal pure returns (uint256) {\n return halfWAD;\n }\n\n function wadMul(uint256 a, uint256 b) internal pure returns (uint256) {\n return halfWAD.add(a.mul(b)).div(WAD);\n }\n\n function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 halfB = b / 2;\n\n return halfB.add(a.mul(WAD)).div(b);\n }\n\n function rayMul(uint256 a, uint256 b) internal pure returns (uint256) {\n return halfRAY.add(a.mul(b)).div(RAY);\n }\n\n function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 halfB = b / 2;\n\n return halfB.add(a.mul(RAY)).div(b);\n }\n\n function rayToWad(uint256 a) internal pure returns (uint256) {\n uint256 halfRatio = WAD_RAY_RATIO / 2;\n\n return halfRatio.add(a).div(WAD_RAY_RATIO);\n }\n\n function rayToPct(uint256 a) internal pure returns (uint16) {\n uint256 halfRatio = PCT_RAY_RATIO / 2;\n\n uint256 val = halfRatio.add(a).div(PCT_RAY_RATIO);\n return SafeCast.toUint16(val);\n }\n\n function wadToPct(uint256 a) internal pure returns (uint16) {\n uint256 halfRatio = PCT_WAD_RATIO / 2;\n\n uint256 val = halfRatio.add(a).div(PCT_WAD_RATIO);\n return SafeCast.toUint16(val);\n }\n\n function wadToRay(uint256 a) internal pure returns (uint256) {\n return a.mul(WAD_RAY_RATIO);\n }\n\n function pctToRay(uint16 a) internal pure returns (uint256) {\n return uint256(a).mul(RAY).div(1e4);\n }\n\n function pctToWad(uint16 a) internal pure returns (uint256) {\n return uint256(a).mul(WAD).div(1e4);\n }\n\n /**\n * @dev calculates base^duration. The code uses the ModExp precompile\n * @return z base^duration, in ray\n */\n function rayPow(uint256 x, uint256 n) internal pure returns (uint256) {\n return _pow(x, n, RAY, rayMul);\n }\n\n function wadPow(uint256 x, uint256 n) internal pure returns (uint256) {\n return _pow(x, n, WAD, wadMul);\n }\n\n function _pow(\n uint256 x,\n uint256 n,\n uint256 p,\n function(uint256, uint256) internal pure returns (uint256) mul\n ) internal pure returns (uint256 z) {\n z = n % 2 != 0 ? x : p;\n\n for (n /= 2; n != 0; n /= 2) {\n x = mul(x, x);\n\n if (n % 2 != 0) {\n z = mul(z, x);\n }\n }\n }\n}\n" + }, + "contracts/MarketLiquidityRewards.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"./interfaces/IMarketLiquidityRewards.sol\";\n\nimport \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/ICollateralManager.sol\";\nimport \"./interfaces/ITellerV2.sol\";\n\nimport { BidState } from \"./TellerV2Storage.sol\";\n\n// Libraries\nimport { MathUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\n/*\n- Allocate and claim rewards for loans based on bidId \n\n- Anyone can allocate rewards and an allocation has specific parameters that can be set to incentivise certain types of loans\n \n*/\n\ncontract MarketLiquidityRewards is IMarketLiquidityRewards, Initializable {\n address immutable tellerV2;\n address immutable marketRegistry;\n address immutable collateralManager;\n\n uint256 allocationCount;\n\n //allocationId => rewardAllocation\n mapping(uint256 => RewardAllocation) public allocatedRewards;\n\n //bidId => allocationId => rewardWasClaimed\n mapping(uint256 => mapping(uint256 => bool)) public rewardClaimedForBid;\n\n modifier onlyMarketOwner(uint256 _marketId) {\n require(\n msg.sender ==\n IMarketRegistry(marketRegistry).getMarketOwner(_marketId),\n \"Only market owner can call this function.\"\n );\n _;\n }\n\n event CreatedAllocation(\n uint256 allocationId,\n address allocator,\n uint256 marketId\n );\n\n event UpdatedAllocation(uint256 allocationId);\n\n event IncreasedAllocation(uint256 allocationId, uint256 amount);\n\n event DecreasedAllocation(uint256 allocationId, uint256 amount);\n\n event DeletedAllocation(uint256 allocationId);\n\n event ClaimedRewards(\n uint256 allocationId,\n uint256 bidId,\n address recipient,\n uint256 amount\n );\n\n constructor(\n address _tellerV2,\n address _marketRegistry,\n address _collateralManager\n ) {\n tellerV2 = _tellerV2;\n marketRegistry = _marketRegistry;\n collateralManager = _collateralManager;\n }\n\n function initialize() external initializer {}\n\n /**\n * @notice Creates a new token allocation and transfers the token amount into escrow in this contract\n * @param _allocation - The RewardAllocation struct data to create\n * @return allocationId_\n */\n function allocateRewards(RewardAllocation calldata _allocation)\n public\n virtual\n returns (uint256 allocationId_)\n {\n allocationId_ = allocationCount++;\n\n require(\n _allocation.allocator == msg.sender,\n \"Invalid allocator address\"\n );\n\n require(\n _allocation.requiredPrincipalTokenAddress != address(0),\n \"Invalid required principal token address\"\n );\n\n IERC20Upgradeable(_allocation.rewardTokenAddress).transferFrom(\n msg.sender,\n address(this),\n _allocation.rewardTokenAmount\n );\n\n allocatedRewards[allocationId_] = _allocation;\n\n emit CreatedAllocation(\n allocationId_,\n _allocation.allocator,\n _allocation.marketId\n );\n }\n\n /**\n * @notice Allows the allocator to update properties of an allocation\n * @param _allocationId - The id for the allocation\n * @param _minimumCollateralPerPrincipalAmount - The required collateralization ratio\n * @param _rewardPerLoanPrincipalAmount - The reward to give per principal amount\n * @param _bidStartTimeMin - The block timestamp that loans must have been accepted after to claim rewards\n * @param _bidStartTimeMax - The block timestamp that loans must have been accepted before to claim rewards\n */\n function updateAllocation(\n uint256 _allocationId,\n uint256 _minimumCollateralPerPrincipalAmount,\n uint256 _rewardPerLoanPrincipalAmount,\n uint32 _bidStartTimeMin,\n uint32 _bidStartTimeMax\n ) public virtual {\n RewardAllocation storage allocation = allocatedRewards[_allocationId];\n\n require(\n msg.sender == allocation.allocator,\n \"Only the allocator can update allocation rewards.\"\n );\n\n allocation\n .minimumCollateralPerPrincipalAmount = _minimumCollateralPerPrincipalAmount;\n allocation.rewardPerLoanPrincipalAmount = _rewardPerLoanPrincipalAmount;\n allocation.bidStartTimeMin = _bidStartTimeMin;\n allocation.bidStartTimeMax = _bidStartTimeMax;\n\n emit UpdatedAllocation(_allocationId);\n }\n\n /**\n * @notice Allows anyone to add tokens to an allocation\n * @param _allocationId - The id for the allocation\n * @param _tokenAmount - The amount of tokens to add\n */\n function increaseAllocationAmount(\n uint256 _allocationId,\n uint256 _tokenAmount\n ) public virtual {\n IERC20Upgradeable(allocatedRewards[_allocationId].rewardTokenAddress)\n .transferFrom(msg.sender, address(this), _tokenAmount);\n allocatedRewards[_allocationId].rewardTokenAmount += _tokenAmount;\n\n emit IncreasedAllocation(_allocationId, _tokenAmount);\n }\n\n /**\n * @notice Allows the allocator to withdraw some or all of the funds within an allocation\n * @param _allocationId - The id for the allocation\n * @param _tokenAmount - The amount of tokens to withdraw\n */\n function deallocateRewards(uint256 _allocationId, uint256 _tokenAmount)\n public\n virtual\n {\n require(\n msg.sender == allocatedRewards[_allocationId].allocator,\n \"Only the allocator can deallocate rewards.\"\n );\n\n //enforce that the token amount withdraw must be LEQ to the reward amount for this allocation\n if (_tokenAmount > allocatedRewards[_allocationId].rewardTokenAmount) {\n _tokenAmount = allocatedRewards[_allocationId].rewardTokenAmount;\n }\n\n //subtract amount reward before transfer\n _decrementAllocatedAmount(_allocationId, _tokenAmount);\n\n IERC20Upgradeable(allocatedRewards[_allocationId].rewardTokenAddress)\n .transfer(msg.sender, _tokenAmount);\n\n //if the allocated rewards are drained completely, delete the storage slot for it\n if (allocatedRewards[_allocationId].rewardTokenAmount == 0) {\n delete allocatedRewards[_allocationId];\n\n emit DeletedAllocation(_allocationId);\n } else {\n emit DecreasedAllocation(_allocationId, _tokenAmount);\n }\n }\n\n struct LoanSummary {\n address borrower;\n address lender;\n uint256 marketId;\n address principalTokenAddress;\n uint256 principalAmount;\n uint32 acceptedTimestamp;\n uint32 lastRepaidTimestamp;\n BidState bidState;\n }\n\n function _getLoanSummary(uint256 _bidId)\n internal\n returns (LoanSummary memory _summary)\n {\n (\n _summary.borrower,\n _summary.lender,\n _summary.marketId,\n _summary.principalTokenAddress,\n _summary.principalAmount,\n _summary.acceptedTimestamp,\n _summary.lastRepaidTimestamp,\n _summary.bidState\n ) = ITellerV2(tellerV2).getLoanSummary(_bidId);\n }\n\n /**\n * @notice Allows a borrower or lender to withdraw the allocated ERC20 reward for their loan\n * @param _allocationId - The id for the reward allocation\n * @param _bidId - The id for the loan. Each loan only grants one reward per allocation.\n */\n function claimRewards(uint256 _allocationId, uint256 _bidId)\n external\n virtual\n {\n RewardAllocation storage allocatedReward = allocatedRewards[\n _allocationId\n ];\n\n //set a flag that this reward was claimed for this bid to defend against re-entrancy\n require(\n !rewardClaimedForBid[_bidId][_allocationId],\n \"reward already claimed\"\n );\n rewardClaimedForBid[_bidId][_allocationId] = true;\n\n //make this a struct ?\n LoanSummary memory loanSummary = _getLoanSummary(_bidId); //ITellerV2(tellerV2).getLoanSummary(_bidId);\n\n address collateralTokenAddress = allocatedReward\n .requiredCollateralTokenAddress;\n\n //require that the loan was started in the correct timeframe\n _verifyLoanStartTime(\n loanSummary.acceptedTimestamp,\n allocatedReward.bidStartTimeMin,\n allocatedReward.bidStartTimeMax\n );\n\n //if a collateral token address is set on the allocation, verify that the bid has enough collateral ratio\n if (collateralTokenAddress != address(0)) {\n uint256 collateralAmount = ICollateralManager(collateralManager)\n .getCollateralAmount(_bidId, collateralTokenAddress);\n\n //require collateral amount\n _verifyCollateralAmount(\n collateralTokenAddress,\n collateralAmount,\n loanSummary.principalTokenAddress,\n loanSummary.principalAmount,\n allocatedReward.minimumCollateralPerPrincipalAmount\n );\n }\n\n require(\n loanSummary.principalTokenAddress ==\n allocatedReward.requiredPrincipalTokenAddress,\n \"Principal token address mismatch for allocation\"\n );\n\n require(\n loanSummary.marketId == allocatedRewards[_allocationId].marketId,\n \"MarketId mismatch for allocation\"\n );\n\n uint256 principalTokenDecimals = IERC20MetadataUpgradeable(\n loanSummary.principalTokenAddress\n ).decimals();\n\n address rewardRecipient = _verifyAndReturnRewardRecipient(\n allocatedReward.allocationStrategy,\n loanSummary.bidState,\n loanSummary.borrower,\n loanSummary.lender\n );\n\n uint32 loanDuration = loanSummary.lastRepaidTimestamp -\n loanSummary.acceptedTimestamp;\n\n uint256 amountToReward = _calculateRewardAmount(\n loanSummary.principalAmount,\n loanDuration,\n principalTokenDecimals,\n allocatedReward.rewardPerLoanPrincipalAmount\n );\n\n if (amountToReward > allocatedReward.rewardTokenAmount) {\n amountToReward = allocatedReward.rewardTokenAmount;\n }\n\n require(amountToReward > 0, \"Nothing to claim.\");\n\n _decrementAllocatedAmount(_allocationId, amountToReward);\n\n //transfer tokens reward to the msgsender\n IERC20Upgradeable(allocatedRewards[_allocationId].rewardTokenAddress)\n .transfer(rewardRecipient, amountToReward);\n\n emit ClaimedRewards(\n _allocationId,\n _bidId,\n rewardRecipient,\n amountToReward\n );\n }\n\n /**\n * @notice Verifies that the bid state is appropriate for claiming rewards based on the allocation strategy and then returns the address of the reward recipient(borrower or lender)\n * @param _strategy - The strategy for the reward allocation.\n * @param _bidState - The bid state of the loan.\n * @param _borrower - The borrower of the loan.\n * @param _lender - The lender of the loan.\n * @return rewardRecipient_ The address that will receive the rewards. Either the borrower or lender.\n */\n function _verifyAndReturnRewardRecipient(\n AllocationStrategy _strategy,\n BidState _bidState,\n address _borrower,\n address _lender\n ) internal virtual returns (address rewardRecipient_) {\n if (_strategy == AllocationStrategy.BORROWER) {\n require(_bidState == BidState.PAID, \"Invalid bid state for loan.\");\n\n rewardRecipient_ = _borrower;\n } else if (_strategy == AllocationStrategy.LENDER) {\n //Loan must have been accepted in the past\n require(\n _bidState >= BidState.ACCEPTED,\n \"Invalid bid state for loan.\"\n );\n\n rewardRecipient_ = _lender;\n } else {\n revert(\"Unknown allocation strategy\");\n }\n }\n\n /**\n * @notice Decrements the amount allocated to keep track of tokens in escrow\n * @param _allocationId - The id for the allocation to decrement\n * @param _amount - The amount of ERC20 to decrement\n */\n function _decrementAllocatedAmount(uint256 _allocationId, uint256 _amount)\n internal\n {\n allocatedRewards[_allocationId].rewardTokenAmount -= _amount;\n }\n\n /**\n * @notice Calculates the reward to claim for the allocation\n * @param _loanPrincipal - The amount of principal for the loan for which to reward\n * @param _loanDuration - The duration of the loan in seconds\n * @param _principalTokenDecimals - The number of decimals of the principal token\n * @param _rewardPerLoanPrincipalAmount - The amount of reward per loan principal amount, expanded by the principal token decimals\n * @return The amount of ERC20 to reward\n */\n function _calculateRewardAmount(\n uint256 _loanPrincipal,\n uint256 _loanDuration,\n uint256 _principalTokenDecimals,\n uint256 _rewardPerLoanPrincipalAmount\n ) internal view returns (uint256) {\n uint256 rewardPerYear = MathUpgradeable.mulDiv(\n _loanPrincipal,\n _rewardPerLoanPrincipalAmount, //expanded by principal token decimals\n 10**_principalTokenDecimals\n );\n\n return MathUpgradeable.mulDiv(rewardPerYear, _loanDuration, 365 days);\n }\n\n /**\n * @notice Verifies that the collateral ratio for the loan was sufficient based on _minimumCollateralPerPrincipalAmount of the allocation\n * @param _collateralTokenAddress - The contract address for the collateral token\n * @param _collateralAmount - The number of decimals of the collateral token\n * @param _principalTokenAddress - The contract address for the principal token\n * @param _principalAmount - The number of decimals of the principal token\n * @param _minimumCollateralPerPrincipalAmount - The amount of collateral required per principal amount. Expanded by the principal token decimals and collateral token decimals.\n */\n function _verifyCollateralAmount(\n address _collateralTokenAddress,\n uint256 _collateralAmount,\n address _principalTokenAddress,\n uint256 _principalAmount,\n uint256 _minimumCollateralPerPrincipalAmount\n ) internal virtual {\n uint256 principalTokenDecimals = IERC20MetadataUpgradeable(\n _principalTokenAddress\n ).decimals();\n\n uint256 collateralTokenDecimals = IERC20MetadataUpgradeable(\n _collateralTokenAddress\n ).decimals();\n\n uint256 minCollateral = _requiredCollateralAmount(\n _principalAmount,\n principalTokenDecimals,\n collateralTokenDecimals,\n _minimumCollateralPerPrincipalAmount\n );\n\n require(\n _collateralAmount >= minCollateral,\n \"Loan does not meet minimum collateralization ratio.\"\n );\n }\n\n /**\n * @notice Calculates the minimum amount of collateral the loan requires based on principal amount\n * @param _principalAmount - The number of decimals of the principal token\n * @param _principalTokenDecimals - The number of decimals of the principal token\n * @param _collateralTokenDecimals - The number of decimals of the collateral token\n * @param _minimumCollateralPerPrincipalAmount - The amount of collateral required per principal amount. Expanded by the principal token decimals and collateral token decimals.\n */\n function _requiredCollateralAmount(\n uint256 _principalAmount,\n uint256 _principalTokenDecimals,\n uint256 _collateralTokenDecimals,\n uint256 _minimumCollateralPerPrincipalAmount\n ) internal view virtual returns (uint256) {\n return\n MathUpgradeable.mulDiv(\n _principalAmount,\n _minimumCollateralPerPrincipalAmount, //expanded by principal token decimals and collateral token decimals\n 10**(_principalTokenDecimals + _collateralTokenDecimals)\n );\n }\n\n /**\n * @notice Verifies that the loan start time is within the bounds set by the allocation requirements\n * @param _loanStartTime - The timestamp when the loan was accepted\n * @param _minStartTime - The minimum time required, after which the loan must have been accepted\n * @param _maxStartTime - The maximum time required, before which the loan must have been accepted\n */\n function _verifyLoanStartTime(\n uint32 _loanStartTime,\n uint32 _minStartTime,\n uint32 _maxStartTime\n ) internal virtual {\n require(\n _minStartTime == 0 || _loanStartTime > _minStartTime,\n \"Loan was accepted before the min start time.\"\n );\n require(\n _maxStartTime == 0 || _loanStartTime < _maxStartTime,\n \"Loan was accepted after the max start time.\"\n );\n }\n\n /**\n * @notice Returns the amount of reward tokens remaining in the allocation\n * @param _allocationId - The id for the allocation\n */\n function getRewardTokenAmount(uint256 _allocationId)\n public\n view\n override\n returns (uint256)\n {\n return allocatedRewards[_allocationId].rewardTokenAmount;\n }\n}\n" + }, + "contracts/MarketRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// Contracts\nimport \"./EAS/TellerAS.sol\";\nimport \"./EAS/TellerASResolver.sol\";\n\n//must continue to use this so storage slots are not broken\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts/utils/Context.sol\";\n\n// Interfaces\nimport \"./interfaces/IMarketRegistry.sol\";\n\n// Libraries\nimport { EnumerableSet } from \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport { PaymentType } from \"./libraries/V2Calculations.sol\";\n\ncontract MarketRegistry is\n IMarketRegistry,\n Initializable,\n Context,\n TellerASResolver\n{\n using EnumerableSet for EnumerableSet.AddressSet;\n\n /** Constant Variables **/\n\n uint256 public constant CURRENT_CODE_VERSION = 8;\n\n /* Storage Variables */\n\n struct Marketplace {\n address owner;\n string metadataURI;\n uint16 marketplaceFeePercent; // 10000 is 100%\n bool lenderAttestationRequired;\n EnumerableSet.AddressSet verifiedLendersForMarket;\n mapping(address => bytes32) lenderAttestationIds;\n uint32 paymentCycleDuration; // unix time (seconds)\n uint32 paymentDefaultDuration; //unix time\n uint32 bidExpirationTime; //unix time\n bool borrowerAttestationRequired;\n EnumerableSet.AddressSet verifiedBorrowersForMarket;\n mapping(address => bytes32) borrowerAttestationIds;\n address feeRecipient;\n PaymentType paymentType;\n PaymentCycleType paymentCycleType;\n }\n\n bytes32 public lenderAttestationSchemaId;\n\n mapping(uint256 => Marketplace) internal markets;\n mapping(bytes32 => uint256) internal __uriToId; //DEPRECATED\n uint256 public marketCount;\n bytes32 private _attestingSchemaId;\n bytes32 public borrowerAttestationSchemaId;\n\n uint256 public version;\n\n mapping(uint256 => bool) private marketIsClosed;\n\n TellerAS public tellerAS;\n\n /* Modifiers */\n\n modifier ownsMarket(uint256 _marketId) {\n require(_getMarketOwner(_marketId) == _msgSender(), \"Not the owner\");\n _;\n }\n\n modifier withAttestingSchema(bytes32 schemaId) {\n _attestingSchemaId = schemaId;\n _;\n _attestingSchemaId = bytes32(0);\n }\n\n /* Events */\n\n event MarketCreated(address indexed owner, uint256 marketId);\n event SetMarketURI(uint256 marketId, string uri);\n event SetPaymentCycleDuration(uint256 marketId, uint32 duration); // DEPRECATED - used for subgraph reference\n event SetPaymentCycle(\n uint256 marketId,\n PaymentCycleType paymentCycleType,\n uint32 value\n );\n event SetPaymentDefaultDuration(uint256 marketId, uint32 duration);\n event SetBidExpirationTime(uint256 marketId, uint32 duration);\n event SetMarketFee(uint256 marketId, uint16 feePct);\n event LenderAttestation(uint256 marketId, address lender);\n event BorrowerAttestation(uint256 marketId, address borrower);\n event LenderRevocation(uint256 marketId, address lender);\n event BorrowerRevocation(uint256 marketId, address borrower);\n event MarketClosed(uint256 marketId);\n event LenderExitMarket(uint256 marketId, address lender);\n event BorrowerExitMarket(uint256 marketId, address borrower);\n event SetMarketOwner(uint256 marketId, address newOwner);\n event SetMarketFeeRecipient(uint256 marketId, address newRecipient);\n event SetMarketLenderAttestation(uint256 marketId, bool required);\n event SetMarketBorrowerAttestation(uint256 marketId, bool required);\n event SetMarketPaymentType(uint256 marketId, PaymentType paymentType);\n\n /* External Functions */\n\n function initialize(TellerAS _tellerAS) external initializer {\n tellerAS = _tellerAS;\n\n lenderAttestationSchemaId = tellerAS.getASRegistry().register(\n \"(uint256 marketId, address lenderAddress)\",\n this\n );\n borrowerAttestationSchemaId = tellerAS.getASRegistry().register(\n \"(uint256 marketId, address borrowerAddress)\",\n this\n );\n }\n\n /**\n * @notice Creates a new market.\n * @param _initialOwner Address who will initially own the market.\n * @param _paymentCycleDuration Length of time in seconds before a bid's next payment is required to be made.\n * @param _paymentDefaultDuration Length of time in seconds before a loan is considered in default for non-payment.\n * @param _bidExpirationTime Length of time in seconds before pending bids expire.\n * @param _requireLenderAttestation Boolean that indicates if lenders require attestation to join market.\n * @param _requireBorrowerAttestation Boolean that indicates if borrowers require attestation to join market.\n * @param _paymentType The payment type for loans in the market.\n * @param _uri URI string to get metadata details about the market.\n * @param _paymentCycleType The payment cycle type for loans in the market - Seconds or Monthly\n * @return marketId_ The market ID of the newly created market.\n */\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n PaymentType _paymentType,\n PaymentCycleType _paymentCycleType,\n string calldata _uri\n ) external returns (uint256 marketId_) {\n marketId_ = _createMarket(\n _initialOwner,\n _paymentCycleDuration,\n _paymentDefaultDuration,\n _bidExpirationTime,\n _feePercent,\n _requireLenderAttestation,\n _requireBorrowerAttestation,\n _paymentType,\n _paymentCycleType,\n _uri\n );\n }\n\n /**\n * @notice Creates a new market.\n * @dev Uses the default EMI payment type.\n * @param _initialOwner Address who will initially own the market.\n * @param _paymentCycleDuration Length of time in seconds before a bid's next payment is required to be made.\n * @param _paymentDefaultDuration Length of time in seconds before a loan is considered in default for non-payment.\n * @param _bidExpirationTime Length of time in seconds before pending bids expire.\n * @param _requireLenderAttestation Boolean that indicates if lenders require attestation to join market.\n * @param _requireBorrowerAttestation Boolean that indicates if borrowers require attestation to join market.\n * @param _uri URI string to get metadata details about the market.\n * @return marketId_ The market ID of the newly created market.\n */\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n string calldata _uri\n ) external returns (uint256 marketId_) {\n marketId_ = _createMarket(\n _initialOwner,\n _paymentCycleDuration,\n _paymentDefaultDuration,\n _bidExpirationTime,\n _feePercent,\n _requireLenderAttestation,\n _requireBorrowerAttestation,\n PaymentType.EMI,\n PaymentCycleType.Seconds,\n _uri\n );\n }\n\n /**\n * @notice Creates a new market.\n * @param _initialOwner Address who will initially own the market.\n * @param _paymentCycleDuration Length of time in seconds before a bid's next payment is required to be made.\n * @param _paymentDefaultDuration Length of time in seconds before a loan is considered in default for non-payment.\n * @param _bidExpirationTime Length of time in seconds before pending bids expire.\n * @param _requireLenderAttestation Boolean that indicates if lenders require attestation to join market.\n * @param _requireBorrowerAttestation Boolean that indicates if borrowers require attestation to join market.\n * @param _paymentType The payment type for loans in the market.\n * @param _uri URI string to get metadata details about the market.\n * @param _paymentCycleType The payment cycle type for loans in the market - Seconds or Monthly\n * @return marketId_ The market ID of the newly created market.\n */\n function _createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n PaymentType _paymentType,\n PaymentCycleType _paymentCycleType,\n string calldata _uri\n ) internal returns (uint256 marketId_) {\n require(_initialOwner != address(0), \"Invalid owner address\");\n // Increment market ID counter\n marketId_ = ++marketCount;\n\n // Set the market owner\n markets[marketId_].owner = _initialOwner;\n\n // Initialize market settings\n _setMarketSettings(\n marketId_,\n _paymentCycleDuration,\n _paymentType,\n _paymentCycleType,\n _paymentDefaultDuration,\n _bidExpirationTime,\n _feePercent,\n _requireBorrowerAttestation,\n _requireLenderAttestation,\n _uri\n );\n\n emit MarketCreated(_initialOwner, marketId_);\n }\n\n /**\n * @notice Closes a market so new bids cannot be added.\n * @param _marketId The market ID for the market to close.\n */\n\n function closeMarket(uint256 _marketId) public ownsMarket(_marketId) {\n if (!marketIsClosed[_marketId]) {\n marketIsClosed[_marketId] = true;\n\n emit MarketClosed(_marketId);\n }\n }\n\n /**\n * @notice Returns the status of a market existing and not being closed.\n * @param _marketId The market ID for the market to check.\n */\n function isMarketOpen(uint256 _marketId)\n public\n view\n override\n returns (bool)\n {\n return\n markets[_marketId].owner != address(0) &&\n !marketIsClosed[_marketId];\n }\n\n /**\n * @notice Returns the status of a market being open or closed for new bids. Does not indicate whether or not a market exists.\n * @param _marketId The market ID for the market to check.\n */\n function isMarketClosed(uint256 _marketId)\n public\n view\n override\n returns (bool)\n {\n return marketIsClosed[_marketId];\n }\n\n /**\n * @notice Adds a lender to a market.\n * @dev See {_attestStakeholder}.\n */\n function attestLender(\n uint256 _marketId,\n address _lenderAddress,\n uint256 _expirationTime\n ) external {\n _attestStakeholder(_marketId, _lenderAddress, _expirationTime, true);\n }\n\n /**\n * @notice Adds a lender to a market via delegated attestation.\n * @dev See {_attestStakeholderViaDelegation}.\n */\n function attestLender(\n uint256 _marketId,\n address _lenderAddress,\n uint256 _expirationTime,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) external {\n _attestStakeholderViaDelegation(\n _marketId,\n _lenderAddress,\n _expirationTime,\n true,\n _v,\n _r,\n _s\n );\n }\n\n /**\n * @notice Removes a lender from an market.\n * @dev See {_revokeStakeholder}.\n */\n function revokeLender(uint256 _marketId, address _lenderAddress) external {\n _revokeStakeholder(_marketId, _lenderAddress, true);\n }\n\n /**\n * @notice Removes a borrower from a market via delegated revocation.\n * @dev See {_revokeStakeholderViaDelegation}.\n */\n function revokeLender(\n uint256 _marketId,\n address _lenderAddress,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) external {\n _revokeStakeholderViaDelegation(\n _marketId,\n _lenderAddress,\n true,\n _v,\n _r,\n _s\n );\n }\n\n /**\n * @notice Allows a lender to voluntarily leave a market.\n * @param _marketId The market ID to leave.\n */\n function lenderExitMarket(uint256 _marketId) external {\n // Remove lender address from market set\n bool response = markets[_marketId].verifiedLendersForMarket.remove(\n _msgSender()\n );\n if (response) {\n emit LenderExitMarket(_marketId, _msgSender());\n }\n }\n\n /**\n * @notice Adds a borrower to a market.\n * @dev See {_attestStakeholder}.\n */\n function attestBorrower(\n uint256 _marketId,\n address _borrowerAddress,\n uint256 _expirationTime\n ) external {\n _attestStakeholder(_marketId, _borrowerAddress, _expirationTime, false);\n }\n\n /**\n * @notice Adds a borrower to a market via delegated attestation.\n * @dev See {_attestStakeholderViaDelegation}.\n */\n function attestBorrower(\n uint256 _marketId,\n address _borrowerAddress,\n uint256 _expirationTime,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) external {\n _attestStakeholderViaDelegation(\n _marketId,\n _borrowerAddress,\n _expirationTime,\n false,\n _v,\n _r,\n _s\n );\n }\n\n /**\n * @notice Removes a borrower from an market.\n * @dev See {_revokeStakeholder}.\n */\n function revokeBorrower(uint256 _marketId, address _borrowerAddress)\n external\n {\n _revokeStakeholder(_marketId, _borrowerAddress, false);\n }\n\n /**\n * @notice Removes a borrower from a market via delegated revocation.\n * @dev See {_revokeStakeholderViaDelegation}.\n */\n function revokeBorrower(\n uint256 _marketId,\n address _borrowerAddress,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) external {\n _revokeStakeholderViaDelegation(\n _marketId,\n _borrowerAddress,\n false,\n _v,\n _r,\n _s\n );\n }\n\n /**\n * @notice Allows a borrower to voluntarily leave a market.\n * @param _marketId The market ID to leave.\n */\n function borrowerExitMarket(uint256 _marketId) external {\n // Remove borrower address from market set\n bool response = markets[_marketId].verifiedBorrowersForMarket.remove(\n _msgSender()\n );\n if (response) {\n emit BorrowerExitMarket(_marketId, _msgSender());\n }\n }\n\n /**\n * @notice Verifies an attestation is valid.\n * @dev This function must only be called by the `attestLender` function above.\n * @param recipient Lender's address who is being attested.\n * @param schema The schema used for the attestation.\n * @param data Data the must include the market ID and lender's address\n * @param\n * @param attestor Market owner's address who signed the attestation.\n * @return Boolean indicating the attestation was successful.\n */\n function resolve(\n address recipient,\n bytes calldata schema,\n bytes calldata data,\n uint256 /* expirationTime */,\n address attestor\n ) external payable override returns (bool) {\n bytes32 attestationSchemaId = keccak256(\n abi.encodePacked(schema, address(this))\n );\n (uint256 marketId, address lenderAddress) = abi.decode(\n data,\n (uint256, address)\n );\n return\n (_attestingSchemaId == attestationSchemaId &&\n recipient == lenderAddress &&\n attestor == _getMarketOwner(marketId)) ||\n attestor == address(this);\n }\n\n /**\n * @notice Transfers ownership of a marketplace.\n * @param _marketId The ID of a market.\n * @param _newOwner Address of the new market owner.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function transferMarketOwnership(uint256 _marketId, address _newOwner)\n public\n ownsMarket(_marketId)\n {\n markets[_marketId].owner = _newOwner;\n emit SetMarketOwner(_marketId, _newOwner);\n }\n\n /**\n * @notice Updates multiple market settings for a given market.\n * @param _marketId The ID of a market.\n * @param _paymentCycleDuration Delinquency duration for new loans\n * @param _newPaymentType The payment type for the market.\n * @param _paymentCycleType The payment cycle type for loans in the market - Seconds or Monthly\n * @param _paymentDefaultDuration Default duration for new loans\n * @param _bidExpirationTime Duration of time before a bid is considered out of date\n * @param _metadataURI A URI that points to a market's metadata.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function updateMarketSettings(\n uint256 _marketId,\n uint32 _paymentCycleDuration,\n PaymentType _newPaymentType,\n PaymentCycleType _paymentCycleType,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _borrowerAttestationRequired,\n bool _lenderAttestationRequired,\n string calldata _metadataURI\n ) public ownsMarket(_marketId) {\n _setMarketSettings(\n _marketId,\n _paymentCycleDuration,\n _newPaymentType,\n _paymentCycleType,\n _paymentDefaultDuration,\n _bidExpirationTime,\n _feePercent,\n _borrowerAttestationRequired,\n _lenderAttestationRequired,\n _metadataURI\n );\n }\n\n /**\n * @notice Sets the fee recipient address for a market.\n * @param _marketId The ID of a market.\n * @param _recipient Address of the new fee recipient.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setMarketFeeRecipient(uint256 _marketId, address _recipient)\n public\n ownsMarket(_marketId)\n {\n markets[_marketId].feeRecipient = _recipient;\n emit SetMarketFeeRecipient(_marketId, _recipient);\n }\n\n /**\n * @notice Sets the metadata URI for a market.\n * @param _marketId The ID of a market.\n * @param _uri A URI that points to a market's metadata.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setMarketURI(uint256 _marketId, string calldata _uri)\n public\n ownsMarket(_marketId)\n {\n //We do string comparison by checking the hashes of the strings against one another\n if (\n keccak256(abi.encodePacked(_uri)) !=\n keccak256(abi.encodePacked(markets[_marketId].metadataURI))\n ) {\n markets[_marketId].metadataURI = _uri;\n\n emit SetMarketURI(_marketId, _uri);\n }\n }\n\n /**\n * @notice Sets the duration of new loans for this market before they turn delinquent.\n * @notice Changing this value does not change the terms of existing loans for this market.\n * @param _marketId The ID of a market.\n * @param _paymentCycleType Cycle type (seconds or monthly)\n * @param _duration Delinquency duration for new loans\n */\n function setPaymentCycle(\n uint256 _marketId,\n PaymentCycleType _paymentCycleType,\n uint32 _duration\n ) public ownsMarket(_marketId) {\n require(\n (_paymentCycleType == PaymentCycleType.Seconds) ||\n (_paymentCycleType == PaymentCycleType.Monthly &&\n _duration == 0),\n \"monthly payment cycle duration cannot be set\"\n );\n Marketplace storage market = markets[_marketId];\n uint32 duration = _paymentCycleType == PaymentCycleType.Seconds\n ? _duration\n : 30 days;\n if (\n _paymentCycleType != market.paymentCycleType ||\n duration != market.paymentCycleDuration\n ) {\n markets[_marketId].paymentCycleType = _paymentCycleType;\n markets[_marketId].paymentCycleDuration = duration;\n\n emit SetPaymentCycle(_marketId, _paymentCycleType, duration);\n }\n }\n\n /**\n * @notice Sets the duration of new loans for this market before they turn defaulted.\n * @notice Changing this value does not change the terms of existing loans for this market.\n * @param _marketId The ID of a market.\n * @param _duration Default duration for new loans\n */\n function setPaymentDefaultDuration(uint256 _marketId, uint32 _duration)\n public\n ownsMarket(_marketId)\n {\n if (_duration != markets[_marketId].paymentDefaultDuration) {\n markets[_marketId].paymentDefaultDuration = _duration;\n\n emit SetPaymentDefaultDuration(_marketId, _duration);\n }\n }\n\n function setBidExpirationTime(uint256 _marketId, uint32 _duration)\n public\n ownsMarket(_marketId)\n {\n if (_duration != markets[_marketId].bidExpirationTime) {\n markets[_marketId].bidExpirationTime = _duration;\n\n emit SetBidExpirationTime(_marketId, _duration);\n }\n }\n\n /**\n * @notice Sets the fee for the market.\n * @param _marketId The ID of a market.\n * @param _newPercent The percentage fee in basis points.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setMarketFeePercent(uint256 _marketId, uint16 _newPercent)\n public\n ownsMarket(_marketId)\n {\n require(_newPercent >= 0 && _newPercent <= 10000, \"invalid percent\");\n if (_newPercent != markets[_marketId].marketplaceFeePercent) {\n markets[_marketId].marketplaceFeePercent = _newPercent;\n emit SetMarketFee(_marketId, _newPercent);\n }\n }\n\n /**\n * @notice Set the payment type for the market.\n * @param _marketId The ID of the market.\n * @param _newPaymentType The payment type for the market.\n */\n function setMarketPaymentType(\n uint256 _marketId,\n PaymentType _newPaymentType\n ) public ownsMarket(_marketId) {\n if (_newPaymentType != markets[_marketId].paymentType) {\n markets[_marketId].paymentType = _newPaymentType;\n emit SetMarketPaymentType(_marketId, _newPaymentType);\n }\n }\n\n /**\n * @notice Enable/disables market whitelist for lenders.\n * @param _marketId The ID of a market.\n * @param _required Boolean indicating if the market requires whitelist.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setLenderAttestationRequired(uint256 _marketId, bool _required)\n public\n ownsMarket(_marketId)\n {\n if (_required != markets[_marketId].lenderAttestationRequired) {\n markets[_marketId].lenderAttestationRequired = _required;\n emit SetMarketLenderAttestation(_marketId, _required);\n }\n }\n\n /**\n * @notice Enable/disables market whitelist for borrowers.\n * @param _marketId The ID of a market.\n * @param _required Boolean indicating if the market requires whitelist.\n *\n * Requirements:\n * - The caller must be the current owner.\n */\n function setBorrowerAttestationRequired(uint256 _marketId, bool _required)\n public\n ownsMarket(_marketId)\n {\n if (_required != markets[_marketId].borrowerAttestationRequired) {\n markets[_marketId].borrowerAttestationRequired = _required;\n emit SetMarketBorrowerAttestation(_marketId, _required);\n }\n }\n\n /**\n * @notice Gets the data associated with a market.\n * @param _marketId The ID of a market.\n */\n function getMarketData(uint256 _marketId)\n public\n view\n returns (\n address owner,\n uint32 paymentCycleDuration,\n uint32 paymentDefaultDuration,\n uint32 loanExpirationTime,\n string memory metadataURI,\n uint16 marketplaceFeePercent,\n bool lenderAttestationRequired\n )\n {\n return (\n markets[_marketId].owner,\n markets[_marketId].paymentCycleDuration,\n markets[_marketId].paymentDefaultDuration,\n markets[_marketId].bidExpirationTime,\n markets[_marketId].metadataURI,\n markets[_marketId].marketplaceFeePercent,\n markets[_marketId].lenderAttestationRequired\n );\n }\n\n /**\n * @notice Gets the attestation requirements for a given market.\n * @param _marketId The ID of the market.\n */\n function getMarketAttestationRequirements(uint256 _marketId)\n public\n view\n returns (\n bool lenderAttestationRequired,\n bool borrowerAttestationRequired\n )\n {\n return (\n markets[_marketId].lenderAttestationRequired,\n markets[_marketId].borrowerAttestationRequired\n );\n }\n\n /**\n * @notice Gets the address of a market's owner.\n * @param _marketId The ID of a market.\n * @return The address of a market's owner.\n */\n function getMarketOwner(uint256 _marketId)\n public\n view\n virtual\n override\n returns (address)\n {\n return _getMarketOwner(_marketId);\n }\n\n /**\n * @notice Gets the address of a market's owner.\n * @param _marketId The ID of a market.\n * @return The address of a market's owner.\n */\n function _getMarketOwner(uint256 _marketId)\n internal\n view\n virtual\n returns (address)\n {\n return markets[_marketId].owner;\n }\n\n /**\n * @notice Gets the fee recipient of a market.\n * @param _marketId The ID of a market.\n * @return The address of a market's fee recipient.\n */\n function getMarketFeeRecipient(uint256 _marketId)\n public\n view\n override\n returns (address)\n {\n address recipient = markets[_marketId].feeRecipient;\n\n if (recipient == address(0)) {\n return _getMarketOwner(_marketId);\n }\n\n return recipient;\n }\n\n /**\n * @notice Gets the metadata URI of a market.\n * @param _marketId The ID of a market.\n * @return URI of a market's metadata.\n */\n function getMarketURI(uint256 _marketId)\n public\n view\n override\n returns (string memory)\n {\n return markets[_marketId].metadataURI;\n }\n\n /**\n * @notice Gets the loan delinquent duration of a market.\n * @param _marketId The ID of a market.\n * @return Duration of a loan until it is delinquent.\n * @return The type of payment cycle for loans in the market.\n */\n function getPaymentCycle(uint256 _marketId)\n public\n view\n override\n returns (uint32, PaymentCycleType)\n {\n return (\n markets[_marketId].paymentCycleDuration,\n markets[_marketId].paymentCycleType\n );\n }\n\n /**\n * @notice Gets the loan default duration of a market.\n * @param _marketId The ID of a market.\n * @return Duration of a loan repayment interval until it is default.\n */\n function getPaymentDefaultDuration(uint256 _marketId)\n public\n view\n override\n returns (uint32)\n {\n return markets[_marketId].paymentDefaultDuration;\n }\n\n /**\n * @notice Get the payment type of a market.\n * @param _marketId the ID of the market.\n * @return The type of payment for loans in the market.\n */\n function getPaymentType(uint256 _marketId)\n public\n view\n override\n returns (PaymentType)\n {\n return markets[_marketId].paymentType;\n }\n\n function getBidExpirationTime(uint256 marketId)\n public\n view\n override\n returns (uint32)\n {\n return markets[marketId].bidExpirationTime;\n }\n\n /**\n * @notice Gets the marketplace fee in basis points\n * @param _marketId The ID of a market.\n * @return fee in basis points\n */\n function getMarketplaceFee(uint256 _marketId)\n public\n view\n override\n returns (uint16 fee)\n {\n return markets[_marketId].marketplaceFeePercent;\n }\n\n /**\n * @notice Checks if a lender has been attested and added to a market.\n * @param _marketId The ID of a market.\n * @param _lenderAddress Address to check.\n * @return isVerified_ Boolean indicating if a lender has been added to a market.\n * @return uuid_ Bytes32 representing the UUID of the lender.\n */\n function isVerifiedLender(uint256 _marketId, address _lenderAddress)\n public\n view\n override\n returns (bool isVerified_, bytes32 uuid_)\n {\n return\n _isVerified(\n _lenderAddress,\n markets[_marketId].lenderAttestationRequired,\n markets[_marketId].lenderAttestationIds,\n markets[_marketId].verifiedLendersForMarket\n );\n }\n\n /**\n * @notice Checks if a borrower has been attested and added to a market.\n * @param _marketId The ID of a market.\n * @param _borrowerAddress Address of the borrower to check.\n * @return isVerified_ Boolean indicating if a borrower has been added to a market.\n * @return uuid_ Bytes32 representing the UUID of the borrower.\n */\n function isVerifiedBorrower(uint256 _marketId, address _borrowerAddress)\n public\n view\n override\n returns (bool isVerified_, bytes32 uuid_)\n {\n return\n _isVerified(\n _borrowerAddress,\n markets[_marketId].borrowerAttestationRequired,\n markets[_marketId].borrowerAttestationIds,\n markets[_marketId].verifiedBorrowersForMarket\n );\n }\n\n /**\n * @notice Gets addresses of all attested lenders.\n * @param _marketId The ID of a market.\n * @param _page Page index to start from.\n * @param _perPage Number of items in a page to return.\n * @return Array of addresses that have been added to a market.\n */\n function getAllVerifiedLendersForMarket(\n uint256 _marketId,\n uint256 _page,\n uint256 _perPage\n ) public view returns (address[] memory) {\n EnumerableSet.AddressSet storage set = markets[_marketId]\n .verifiedLendersForMarket;\n\n return _getStakeholdersForMarket(set, _page, _perPage);\n }\n\n /**\n * @notice Gets addresses of all attested borrowers.\n * @param _marketId The ID of the market.\n * @param _page Page index to start from.\n * @param _perPage Number of items in a page to return.\n * @return Array of addresses that have been added to a market.\n */\n function getAllVerifiedBorrowersForMarket(\n uint256 _marketId,\n uint256 _page,\n uint256 _perPage\n ) public view returns (address[] memory) {\n EnumerableSet.AddressSet storage set = markets[_marketId]\n .verifiedBorrowersForMarket;\n return _getStakeholdersForMarket(set, _page, _perPage);\n }\n\n /**\n * @notice Sets multiple market settings for a given market.\n * @param _marketId The ID of a market.\n * @param _paymentCycleDuration Delinquency duration for new loans\n * @param _newPaymentType The payment type for the market.\n * @param _paymentCycleType The payment cycle type for loans in the market - Seconds or Monthly\n * @param _paymentDefaultDuration Default duration for new loans\n * @param _bidExpirationTime Duration of time before a bid is considered out of date\n * @param _metadataURI A URI that points to a market's metadata.\n */\n function _setMarketSettings(\n uint256 _marketId,\n uint32 _paymentCycleDuration,\n PaymentType _newPaymentType,\n PaymentCycleType _paymentCycleType,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _borrowerAttestationRequired,\n bool _lenderAttestationRequired,\n string calldata _metadataURI\n ) internal {\n setMarketURI(_marketId, _metadataURI);\n setPaymentDefaultDuration(_marketId, _paymentDefaultDuration);\n setBidExpirationTime(_marketId, _bidExpirationTime);\n setMarketFeePercent(_marketId, _feePercent);\n setLenderAttestationRequired(_marketId, _lenderAttestationRequired);\n setBorrowerAttestationRequired(_marketId, _borrowerAttestationRequired);\n setMarketPaymentType(_marketId, _newPaymentType);\n setPaymentCycle(_marketId, _paymentCycleType, _paymentCycleDuration);\n }\n\n /**\n * @notice Gets addresses of all attested relevant stakeholders.\n * @param _set The stored set of stakeholders to index from.\n * @param _page Page index to start from.\n * @param _perPage Number of items in a page to return.\n * @return stakeholders_ Array of addresses that have been added to a market.\n */\n function _getStakeholdersForMarket(\n EnumerableSet.AddressSet storage _set,\n uint256 _page,\n uint256 _perPage\n ) internal view returns (address[] memory stakeholders_) {\n uint256 len = _set.length();\n\n uint256 start = _page * _perPage;\n if (start <= len) {\n uint256 end = start + _perPage;\n // Ensure we do not go out of bounds\n if (end > len) {\n end = len;\n }\n\n stakeholders_ = new address[](end - start);\n for (uint256 i = start; i < end; i++) {\n stakeholders_[i] = _set.at(i);\n }\n }\n }\n\n /* Internal Functions */\n\n /**\n * @notice Adds a stakeholder (lender or borrower) to a market.\n * @param _marketId The market ID to add a borrower to.\n * @param _stakeholderAddress The address of the stakeholder to add to the market.\n * @param _expirationTime The expiration time of the attestation.\n * @param _expirationTime The expiration time of the attestation.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n */\n function _attestStakeholder(\n uint256 _marketId,\n address _stakeholderAddress,\n uint256 _expirationTime,\n bool _isLender\n )\n internal\n virtual\n withAttestingSchema(\n _isLender ? lenderAttestationSchemaId : borrowerAttestationSchemaId\n )\n {\n require(\n _msgSender() == _getMarketOwner(_marketId),\n \"Not the market owner\"\n );\n\n // Submit attestation for borrower to join a market\n bytes32 uuid = tellerAS.attest(\n _stakeholderAddress,\n _attestingSchemaId, // set by the modifier\n _expirationTime,\n 0,\n abi.encode(_marketId, _stakeholderAddress)\n );\n _attestStakeholderVerification(\n _marketId,\n _stakeholderAddress,\n uuid,\n _isLender\n );\n }\n\n /**\n * @notice Adds a stakeholder (lender or borrower) to a market via delegated attestation.\n * @dev The signature must match that of the market owner.\n * @param _marketId The market ID to add a lender to.\n * @param _stakeholderAddress The address of the lender to add to the market.\n * @param _expirationTime The expiration time of the attestation.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n * @param _v Signature value\n * @param _r Signature value\n * @param _s Signature value\n */\n function _attestStakeholderViaDelegation(\n uint256 _marketId,\n address _stakeholderAddress,\n uint256 _expirationTime,\n bool _isLender,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n )\n internal\n virtual\n withAttestingSchema(\n _isLender ? lenderAttestationSchemaId : borrowerAttestationSchemaId\n )\n {\n // NOTE: block scope to prevent stack too deep!\n bytes32 uuid;\n {\n bytes memory data = abi.encode(_marketId, _stakeholderAddress);\n address attestor = _getMarketOwner(_marketId);\n // Submit attestation for stakeholder to join a market (attestation must be signed by market owner)\n uuid = tellerAS.attestByDelegation(\n _stakeholderAddress,\n _attestingSchemaId, // set by the modifier\n _expirationTime,\n 0,\n data,\n attestor,\n _v,\n _r,\n _s\n );\n }\n _attestStakeholderVerification(\n _marketId,\n _stakeholderAddress,\n uuid,\n _isLender\n );\n }\n\n /**\n * @notice Adds a stakeholder (borrower/lender) to a market.\n * @param _marketId The market ID to add a stakeholder to.\n * @param _stakeholderAddress The address of the stakeholder to add to the market.\n * @param _uuid The UUID of the attestation created.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n */\n function _attestStakeholderVerification(\n uint256 _marketId,\n address _stakeholderAddress,\n bytes32 _uuid,\n bool _isLender\n ) internal virtual {\n if (_isLender) {\n // Store the lender attestation ID for the market ID\n markets[_marketId].lenderAttestationIds[\n _stakeholderAddress\n ] = _uuid;\n // Add lender address to market set\n markets[_marketId].verifiedLendersForMarket.add(\n _stakeholderAddress\n );\n\n emit LenderAttestation(_marketId, _stakeholderAddress);\n } else {\n // Store the lender attestation ID for the market ID\n markets[_marketId].borrowerAttestationIds[\n _stakeholderAddress\n ] = _uuid;\n // Add lender address to market set\n markets[_marketId].verifiedBorrowersForMarket.add(\n _stakeholderAddress\n );\n\n emit BorrowerAttestation(_marketId, _stakeholderAddress);\n }\n }\n\n /**\n * @notice Removes a stakeholder from an market.\n * @dev The caller must be the market owner.\n * @param _marketId The market ID to remove the borrower from.\n * @param _stakeholderAddress The address of the borrower to remove from the market.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n */\n function _revokeStakeholder(\n uint256 _marketId,\n address _stakeholderAddress,\n bool _isLender\n ) internal virtual {\n require(\n _msgSender() == _getMarketOwner(_marketId),\n \"Not the market owner\"\n );\n\n bytes32 uuid = _revokeStakeholderVerification(\n _marketId,\n _stakeholderAddress,\n _isLender\n );\n // NOTE: Disabling the call to revoke the attestation on EAS contracts\n // tellerAS.revoke(uuid);\n }\n\n /**\n * @notice Removes a stakeholder from an market via delegated revocation.\n * @param _marketId The market ID to remove the borrower from.\n * @param _stakeholderAddress The address of the borrower to remove from the market.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n * @param _v Signature value\n * @param _r Signature value\n * @param _s Signature value\n */\n function _revokeStakeholderViaDelegation(\n uint256 _marketId,\n address _stakeholderAddress,\n bool _isLender,\n uint8 _v,\n bytes32 _r,\n bytes32 _s\n ) internal {\n bytes32 uuid = _revokeStakeholderVerification(\n _marketId,\n _stakeholderAddress,\n _isLender\n );\n // NOTE: Disabling the call to revoke the attestation on EAS contracts\n // address attestor = markets[_marketId].owner;\n // tellerAS.revokeByDelegation(uuid, attestor, _v, _r, _s);\n }\n\n /**\n * @notice Removes a stakeholder (borrower/lender) from a market.\n * @param _marketId The market ID to remove the lender from.\n * @param _stakeholderAddress The address of the stakeholder to remove from the market.\n * @param _isLender Boolean indicating if the stakeholder is a lender. Otherwise it is a borrower.\n * @return uuid_ The ID of the previously verified attestation.\n */\n function _revokeStakeholderVerification(\n uint256 _marketId,\n address _stakeholderAddress,\n bool _isLender\n ) internal virtual returns (bytes32 uuid_) {\n if (_isLender) {\n uuid_ = markets[_marketId].lenderAttestationIds[\n _stakeholderAddress\n ];\n // Remove lender address from market set\n markets[_marketId].verifiedLendersForMarket.remove(\n _stakeholderAddress\n );\n\n emit LenderRevocation(_marketId, _stakeholderAddress);\n } else {\n uuid_ = markets[_marketId].borrowerAttestationIds[\n _stakeholderAddress\n ];\n // Remove borrower address from market set\n markets[_marketId].verifiedBorrowersForMarket.remove(\n _stakeholderAddress\n );\n\n emit BorrowerRevocation(_marketId, _stakeholderAddress);\n }\n }\n\n /**\n * @notice Checks if a stakeholder has been attested and added to a market.\n * @param _stakeholderAddress Address of the stakeholder to check.\n * @param _attestationRequired Stored boolean indicating if attestation is required for the stakeholder class.\n * @param _stakeholderAttestationIds Mapping of attested Ids for the stakeholder class.\n */\n function _isVerified(\n address _stakeholderAddress,\n bool _attestationRequired,\n mapping(address => bytes32) storage _stakeholderAttestationIds,\n EnumerableSet.AddressSet storage _verifiedStakeholderForMarket\n ) internal view virtual returns (bool isVerified_, bytes32 uuid_) {\n if (_attestationRequired) {\n isVerified_ =\n _verifiedStakeholderForMarket.contains(_stakeholderAddress) &&\n tellerAS.isAttestationActive(\n _stakeholderAttestationIds[_stakeholderAddress]\n );\n uuid_ = _stakeholderAttestationIds[_stakeholderAddress];\n } else {\n isVerified_ = true;\n }\n }\n}\n" + }, + "contracts/mock/LenderCommitmentForwarderMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n//import \"../TellerV2MarketForwarder.sol\";\n\nimport \"../TellerV2Context.sol\";\n\n//import { LenderCommitmentForwarder } from \"../contracts/LenderCommitmentForwarder.sol\";\n\nimport \"../interfaces/ITellerV2.sol\";\nimport \"../interfaces/ILenderCommitmentForwarder.sol\";\n\nimport \"../interfaces/ITellerV2MarketForwarder.sol\";\n\nimport { Collateral, CollateralType } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\n\nimport \"../mock/MarketRegistryMock.sol\";\n\ncontract LenderCommitmentForwarderMock is\n ILenderCommitmentForwarder,\n ITellerV2MarketForwarder\n{\n mapping(uint256 => Commitment) public commitments;\n\n uint256 commitmentCount;\n\n bool public submitBidWithCollateralWasCalled;\n bool public acceptBidWasCalled;\n bool public submitBidWasCalled;\n bool public acceptCommitmentWithRecipientWasCalled;\n bool public acceptCommitmentWithRecipientAndProofWasCalled;\n\n mapping(uint256 => uint256) public commitmentPrincipalAccepted;\n\n constructor() {}\n\n function createCommitment(\n Commitment calldata _commitment,\n address[] calldata _borrowerAddressList\n ) external returns (uint256) {}\n\n function setCommitment(uint256 _commitmentId, Commitment memory _commitment)\n public\n {\n commitments[_commitmentId] = _commitment;\n }\n\n function getCommitmentLender(uint256 _commitmentId)\n public\n view\n returns (address)\n {\n return commitments[_commitmentId].lender;\n }\n\n function getCommitmentMarketId(uint256 _commitmentId)\n public\n view\n returns (uint256)\n {\n return commitments[_commitmentId].marketId;\n }\n\n function getCommitmentAcceptedPrincipal(uint256 _commitmentId)\n public\n view\n returns (uint256)\n {\n return commitmentPrincipalAccepted[_commitmentId];\n }\n\n function getCommitmentMaxPrincipal(uint256 _commitmentId)\n public\n view\n returns (uint256)\n {\n return commitments[_commitmentId].maxPrincipal;\n }\n\n /* function _getEscrowCollateralTypeSuper(CommitmentCollateralType _type)\n public\n returns (CollateralType)\n {\n return super._getEscrowCollateralType(_type);\n }\n\n function validateCommitmentSuper(uint256 _commitmentId) public {\n super.validateCommitment(commitments[_commitmentId]);\n }*/\n\n function acceptCommitmentWithRecipient(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration\n ) public returns (uint256 bidId) {\n acceptCommitmentWithRecipientWasCalled = true;\n\n Commitment storage commitment = commitments[_commitmentId];\n\n address lendingToken = commitment.principalTokenAddress;\n\n _mockAcceptCommitmentTokenTransfer(\n lendingToken,\n _principalAmount,\n _recipient\n );\n }\n\n function acceptCommitmentWithRecipientAndProof(\n uint256 _commitmentId,\n uint256 _principalAmount,\n uint256 _collateralAmount,\n uint256 _collateralTokenId,\n address _collateralTokenAddress,\n address _recipient,\n uint16 _interestRate,\n uint32 _loanDuration,\n bytes32[] calldata _merkleProof\n ) public returns (uint256 bidId) {\n acceptCommitmentWithRecipientAndProofWasCalled = true;\n\n Commitment storage commitment = commitments[_commitmentId];\n\n address lendingToken = commitment.principalTokenAddress;\n\n _mockAcceptCommitmentTokenTransfer(\n lendingToken,\n _principalAmount,\n _recipient\n );\n }\n\n function _mockAcceptCommitmentTokenTransfer(\n address lendingToken,\n uint256 principalAmount,\n address _recipient\n ) internal {\n IERC20(lendingToken).transfer(_recipient, principalAmount);\n }\n\n /*\n Override methods \n */\n\n /* function _submitBid(CreateLoanArgs memory, address)\n internal\n override\n returns (uint256 bidId)\n {\n submitBidWasCalled = true;\n return 1;\n }\n\n function _submitBidWithCollateral(CreateLoanArgs memory, address)\n internal\n override\n returns (uint256 bidId)\n {\n submitBidWithCollateralWasCalled = true;\n return 1;\n }\n\n function _acceptBid(uint256, address) internal override returns (bool) {\n acceptBidWasCalled = true;\n\n return true;\n }\n */\n}\n" + }, + "contracts/mock/MarketRegistryMock.sol": { + "content": "pragma solidity ^0.8.0;\n\n// SPDX-License-Identifier: MIT\n\nimport \"../interfaces/IMarketRegistry.sol\";\nimport { PaymentType } from \"../libraries/V2Calculations.sol\";\n\ncontract MarketRegistryMock is IMarketRegistry {\n //address marketOwner;\n\n address public globalMarketOwner;\n address public globalMarketFeeRecipient;\n bool public globalMarketsClosed;\n\n bool public globalBorrowerIsVerified = true;\n bool public globalLenderIsVerified = true;\n\n constructor() {}\n\n function initialize(TellerAS _tellerAS) external {}\n\n function isVerifiedLender(uint256 _marketId, address _lenderAddress)\n public\n view\n returns (bool isVerified_, bytes32 uuid_)\n {\n isVerified_ = globalLenderIsVerified;\n }\n\n function isMarketOpen(uint256 _marketId) public view returns (bool) {\n return !globalMarketsClosed;\n }\n\n function isMarketClosed(uint256 _marketId) public view returns (bool) {\n return globalMarketsClosed;\n }\n\n function isVerifiedBorrower(uint256 _marketId, address _borrower)\n public\n view\n returns (bool isVerified_, bytes32 uuid_)\n {\n isVerified_ = globalBorrowerIsVerified;\n }\n\n function getMarketOwner(uint256 _marketId)\n public\n view\n override\n returns (address)\n {\n return address(globalMarketOwner);\n }\n\n function getMarketFeeRecipient(uint256 _marketId)\n public\n view\n returns (address)\n {\n return address(globalMarketFeeRecipient);\n }\n\n function getMarketURI(uint256 _marketId)\n public\n view\n returns (string memory)\n {\n return \"url://\";\n }\n\n function getPaymentCycle(uint256 _marketId)\n public\n view\n returns (uint32, PaymentCycleType)\n {\n return (1000, PaymentCycleType.Seconds);\n }\n\n function getPaymentDefaultDuration(uint256 _marketId)\n public\n view\n returns (uint32)\n {\n return 1000;\n }\n\n function getBidExpirationTime(uint256 _marketId)\n public\n view\n returns (uint32)\n {\n return 1000;\n }\n\n function getMarketplaceFee(uint256 _marketId) public view returns (uint16) {\n return 1000;\n }\n\n function setMarketOwner(address _owner) public {\n globalMarketOwner = _owner;\n }\n\n function setMarketFeeRecipient(address _feeRecipient) public {\n globalMarketFeeRecipient = _feeRecipient;\n }\n\n function getPaymentType(uint256 _marketId)\n public\n view\n returns (PaymentType)\n {}\n\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n PaymentType _paymentType,\n PaymentCycleType _paymentCycleType,\n string calldata _uri\n ) public returns (uint256) {}\n\n function createMarket(\n address _initialOwner,\n uint32 _paymentCycleDuration,\n uint32 _paymentDefaultDuration,\n uint32 _bidExpirationTime,\n uint16 _feePercent,\n bool _requireLenderAttestation,\n bool _requireBorrowerAttestation,\n string calldata _uri\n ) public returns (uint256) {}\n\n function closeMarket(uint256 _marketId) public {}\n\n function mock_setGlobalMarketsClosed(bool closed) public {\n globalMarketsClosed = closed;\n }\n\n function mock_setBorrowerIsVerified(bool verified) public {\n globalBorrowerIsVerified = verified;\n }\n\n function mock_setLenderIsVerified(bool verified) public {\n globalLenderIsVerified = verified;\n }\n}\n" + }, + "contracts/mock/TellerV2SolMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0 <0.9.0;\n\nimport \"../TellerV2.sol\";\nimport \"../interfaces/ITellerV2.sol\";\nimport \"../interfaces/IProtocolFee.sol\";\nimport \"../TellerV2Context.sol\";\nimport \"../pausing/HasProtocolPausingManager.sol\";\nimport { Collateral } from \"../interfaces/escrow/ICollateralEscrowV1.sol\";\nimport { LoanDetails, Payment, BidState } from \"../TellerV2Storage.sol\";\n\nimport { ILoanRepaymentCallbacks } from \"../interfaces/ILoanRepaymentCallbacks.sol\";\n\n\n/*\nThis is only used for sol test so its named specifically to avoid being used for the typescript tests.\n*/\ncontract TellerV2SolMock is \nITellerV2,\nIProtocolFee, \nTellerV2Storage , \nHasProtocolPausingManager,\nILoanRepaymentCallbacks\n{\n uint256 public amountOwedMockPrincipal;\n uint256 public amountOwedMockInterest;\n address public approvedForwarder;\n bool public isPausedMock;\n\n address public mockOwner;\n\n\n PaymentCycleType globalBidPaymentCycleType = PaymentCycleType.Seconds;\n uint32 globalBidPaymentCycleDuration = 3000;\n\n uint256 mockLoanDefaultTimestamp;\n bool public lenderCloseLoanWasCalled;\n\n function setMarketRegistry(address _marketRegistry) public {\n marketRegistry = IMarketRegistry(_marketRegistry);\n }\n\n function setProtocolPausingManager(address _protocolPausingManager) public {\n _setProtocolPausingManager(_protocolPausingManager);\n }\n\n function getMarketRegistry() external view returns (IMarketRegistry) {\n return marketRegistry;\n }\n\n function protocolFee() external view returns (uint16) {\n return 100;\n }\n\n\n function getEscrowVault() external view returns(address){\n return address(0);\n }\n\n\n function paused() external view returns(bool){\n return isPausedMock;\n }\n\n\n function setMockOwner(address _newOwner) external {\n mockOwner = _newOwner;\n }\n function owner() external view returns(address){\n return mockOwner;\n }\n\n function isPauser(address _account) public view returns(bool){\n return false; //for now \n }\n\n function approveMarketForwarder(uint256 _marketId, address _forwarder)\n external\n {\n approvedForwarder = _forwarder;\n }\n\n\n function submitBid(\n address _lendingToken,\n uint256 _marketId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata,\n address _receiver\n ) public returns (uint256 bidId_) {\n \n\n\n bidId_ = bidId;\n\n Bid storage bid = bids[bidId_];\n bid.borrower = msg.sender;\n bid.receiver = _receiver != address(0) ? _receiver : bid.borrower;\n bid.marketplaceId = _marketId;\n bid.loanDetails.lendingToken = IERC20(_lendingToken);\n bid.loanDetails.principal = _principal;\n bid.loanDetails.loanDuration = _duration;\n bid.loanDetails.timestamp = uint32(block.timestamp);\n\n /*(bid.terms.paymentCycle, bidPaymentCycleType[bidId]) = marketRegistry\n .getPaymentCycle(_marketId);*/\n\n bid.terms.APR = _APR;\n\n bidId++; //nextBidId\n\n }\n\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver,\n Collateral[] calldata _collateralInfo\n ) public returns (uint256 bidId_) {\n submitBid(\n _lendingToken,\n _marketplaceId,\n _principal,\n _duration,\n _APR,\n _metadataURI,\n _receiver\n );\n }\n\n function lenderCloseLoan(uint256 _bidId) external {\n lenderCloseLoanWasCalled = true;\n }\n\n function lenderCloseLoanWithRecipient(uint256 _bidId, address _recipient)\n external\n {\n lenderCloseLoanWasCalled = true;\n }\n\n function getLoanDefaultTimestamp(uint256 _bidId)\n external\n view\n returns (uint256)\n {\n return mockLoanDefaultTimestamp;\n }\n\n function liquidateLoanFull(uint256 _bidId) external {}\n\n function liquidateLoanFullWithRecipient(uint256 _bidId, address _recipient)\n external\n {}\n\n function repayLoanMinimum(uint256 _bidId) external {}\n\n function repayLoanFull(uint256 _bidId) external {\n Bid storage bid = bids[_bidId];\n\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bids[_bidId],\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n\n uint256 _amount = owedPrincipal + interest;\n\n IERC20(bid.loanDetails.lendingToken).transferFrom(\n msg.sender,\n address(this),\n _amount\n );\n }\n\n function repayLoan(uint256 _bidId, uint256 _amount) public {\n Bid storage bid = bids[_bidId];\n\n IERC20(bid.loanDetails.lendingToken).transferFrom(\n msg.sender,\n address(this),\n _amount\n );\n }\n\n /*\n * @notice Calculates the minimum payment amount due for a loan.\n * @param _bidId The id of the loan bid to get the payment amount for.\n */\n function calculateAmountDue(uint256 _bidId, uint256 _timestamp)\n public\n view\n returns (Payment memory due)\n {\n if (bids[_bidId].state != BidState.ACCEPTED) return due;\n\n (, uint256 duePrincipal, uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bids[_bidId],\n _timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n due.principal = duePrincipal;\n due.interest = interest;\n }\n\n function calculateAmountOwed(uint256 _bidId, uint256 _timestamp)\n public\n view\n returns (Payment memory due)\n {\n if (bids[_bidId].state != BidState.ACCEPTED) return due;\n\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bids[_bidId],\n _timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n due.principal = owedPrincipal;\n due.interest = interest;\n }\n\n function lenderAcceptBid(uint256 _bidId)\n public\n returns (\n uint256 amountToProtocol,\n uint256 amountToMarketplace,\n uint256 amountToBorrower\n )\n {\n Bid storage bid = bids[_bidId];\n\n bid.lender = msg.sender;\n\n bid.state = BidState.ACCEPTED;\n\n //send tokens to caller\n IERC20(bid.loanDetails.lendingToken).transferFrom(\n bid.lender,\n bid.receiver,\n bid.loanDetails.principal\n );\n //for the reciever\n\n return (0, bid.loanDetails.principal, 0);\n }\n\n function getBidState(uint256 _bidId)\n public\n view\n virtual\n returns (BidState)\n {\n return bids[_bidId].state;\n }\n\n function getLoanDetails(uint256 _bidId)\n public\n view\n returns (LoanDetails memory)\n {\n return bids[_bidId].loanDetails;\n }\n\n function getBorrowerActiveLoanIds(address _borrower)\n public\n view\n returns (uint256[] memory)\n {}\n\n function isLoanDefaulted(uint256 _bidId)\n public\n view\n virtual\n returns (bool)\n {}\n\n function isLoanLiquidateable(uint256 _bidId)\n public\n view\n virtual\n returns (bool)\n {}\n\n function isPaymentLate(uint256 _bidId) public view returns (bool) {}\n\n function getLoanBorrower(uint256 _bidId)\n external\n view\n virtual\n returns (address borrower_)\n {\n borrower_ = bids[_bidId].borrower;\n }\n\n function getLoanLender(uint256 _bidId)\n external\n view\n virtual\n returns (address lender_)\n {\n lender_ = bids[_bidId].lender;\n }\n\n function getLoanMarketId(uint256 _bidId)\n external\n view\n returns (uint256 _marketId)\n {\n _marketId = bids[_bidId].marketplaceId;\n }\n\n function getLoanLendingToken(uint256 _bidId)\n external\n view\n returns (address token_)\n {\n token_ = address(bids[_bidId].loanDetails.lendingToken);\n }\n\n function getLoanSummary(uint256 _bidId)\n external\n view\n returns (\n address borrower,\n address lender,\n uint256 marketId,\n address principalTokenAddress,\n uint256 principalAmount,\n uint32 acceptedTimestamp,\n uint32 lastRepaidTimestamp,\n BidState bidState\n )\n {\n Bid storage bid = bids[_bidId];\n\n borrower = bid.borrower;\n lender = bid.lender;\n marketId = bid.marketplaceId;\n principalTokenAddress = address(bid.loanDetails.lendingToken);\n principalAmount = bid.loanDetails.principal;\n acceptedTimestamp = bid.loanDetails.acceptedTimestamp;\n lastRepaidTimestamp = bid.loanDetails.lastRepaidTimestamp;\n bidState = bid.state;\n }\n\n function setLastRepaidTimestamp(uint256 _bidId, uint32 _timestamp) public {\n bids[_bidId].loanDetails.lastRepaidTimestamp = _timestamp;\n }\n\n\n\n function mock_setLoanDefaultTimestamp(\n uint256 _defaultedAt\n ) external returns (uint256){\n mockLoanDefaultTimestamp = _defaultedAt;\n } \n\n\n\n function getRepaymentListenerForBid(uint256 _bidId)\n public\n view\n returns (address)\n {}\n\n function setRepaymentListenerForBid(uint256 _bidId, address _listener)\n public\n {}\n\n\n function _getBidPaymentCycleType(uint256 _bidId)\n internal\n view\n returns (PaymentCycleType)\n {\n /* bytes32 bidTermsId = bidMarketTermsId[_bidId];\n if (bidTermsId != bytes32(0)) {\n return marketRegistry.getPaymentCycleTypeForTerms(bidTermsId);\n }*/\n\n return globalBidPaymentCycleType;\n }\n\n function _getBidPaymentCycleDuration(uint256 _bidId)\n internal\n view\n returns (uint32)\n {\n /* bytes32 bidTermsId = bidMarketTermsId[_bidId];\n if (bidTermsId != bytes32(0)) {\n return marketRegistry.getPaymentCycleDurationForTerms(bidTermsId);\n }*/\n\n Bid storage bid = bids[_bidId];\n\n return globalBidPaymentCycleDuration;\n }\n}\n" + }, + "contracts/pausing/HasProtocolPausingManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\n \n \n//import \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n \n\nimport \"../interfaces/IHasProtocolPausingManager.sol\";\n\nimport \"../interfaces/IProtocolPausingManager.sol\";\n \n\nabstract contract HasProtocolPausingManager \n is \n IHasProtocolPausingManager \n {\n \n\n bool private __paused;// .. Deprecated , handled by pausing manager \n\n address private _protocolPausingManager;\n \n\n modifier whenLiquidationsNotPaused() {\n require(! IProtocolPausingManager(_protocolPausingManager). liquidationsPaused(), \"Liquidations paused\" );\n \n _;\n }\n\n //rename to when protocol not paused ?\n modifier whenProtocolNotPaused() {\n require(! IProtocolPausingManager(_protocolPausingManager). protocolPaused(), \"Protocol paused\" );\n \n _;\n }\n \n\n //onlyinitializing? \n function _setProtocolPausingManager(address protocolPausingManager) internal {\n _protocolPausingManager = protocolPausingManager ;\n }\n\n\n function getProtocolPausingManager() public view returns (address){\n\n return _protocolPausingManager;\n }\n\n \n /* \n function isPauser(address _address) public view returns (bool){\n\n return IProtocolPausingManager(_protocolPausingManager). isPauser(_address) ;\n }\n\n function getLastUnpausedAt() \n external view \n returns (uint256) {\n\n return IPausableTimestamp(_protocolPausingManager).getLastUnpausedAt();\n\n } \n */\n\n \n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[48] private __gap;\n}\n" + }, + "contracts/ProtocolFee.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract ProtocolFee is OwnableUpgradeable {\n // Protocol fee set for loan processing.\n uint16 private _protocolFee;\n\n /**\n * @notice This event is emitted when the protocol fee has been updated.\n * @param newFee The new protocol fee set.\n * @param oldFee The previously set protocol fee.\n */\n event ProtocolFeeSet(uint16 newFee, uint16 oldFee);\n\n /**\n * @notice Initialized the protocol fee.\n * @param initFee The initial protocol fee to be set on the protocol.\n */\n function __ProtocolFee_init(uint16 initFee) internal onlyInitializing {\n __Ownable_init();\n __ProtocolFee_init_unchained(initFee);\n }\n\n function __ProtocolFee_init_unchained(uint16 initFee)\n internal\n onlyInitializing\n {\n setProtocolFee(initFee);\n }\n\n /**\n * @notice Returns the current protocol fee.\n */\n function protocolFee() public view virtual returns (uint16) {\n return _protocolFee;\n }\n\n /**\n * @notice Lets the DAO/owner of the protocol to set a new protocol fee.\n * @param newFee The new protocol fee to be set.\n */\n function setProtocolFee(uint16 newFee) public virtual onlyOwner {\n // Skip if the fee is the same\n if (newFee == _protocolFee) return;\n\n uint16 oldFee = _protocolFee;\n _protocolFee = newFee;\n emit ProtocolFeeSet(newFee, oldFee);\n }\n}\n" + }, + "contracts/ReputationManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0 <0.9.0;\n\n// Interfaces\nimport \"./interfaces/IReputationManager.sol\";\nimport \"./interfaces/ITellerV2.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n// Libraries\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\n\ncontract ReputationManager is IReputationManager, Initializable {\n using EnumerableSet for EnumerableSet.UintSet;\n\n bytes32 public constant CONTROLLER = keccak256(\"CONTROLLER\");\n\n ITellerV2 public tellerV2;\n mapping(address => EnumerableSet.UintSet) private _delinquencies;\n mapping(address => EnumerableSet.UintSet) private _defaults;\n mapping(address => EnumerableSet.UintSet) private _currentDelinquencies;\n mapping(address => EnumerableSet.UintSet) private _currentDefaults;\n\n event MarkAdded(\n address indexed account,\n RepMark indexed repMark,\n uint256 bidId\n );\n event MarkRemoved(\n address indexed account,\n RepMark indexed repMark,\n uint256 bidId\n );\n\n /**\n * @notice Initializes the proxy.\n */\n function initialize(address _tellerV2) external initializer {\n tellerV2 = ITellerV2(_tellerV2);\n }\n\n function getDelinquentLoanIds(address _account)\n public\n override\n returns (uint256[] memory)\n {\n updateAccountReputation(_account);\n return _delinquencies[_account].values();\n }\n\n function getDefaultedLoanIds(address _account)\n public\n override\n returns (uint256[] memory)\n {\n updateAccountReputation(_account);\n return _defaults[_account].values();\n }\n\n function getCurrentDelinquentLoanIds(address _account)\n public\n override\n returns (uint256[] memory)\n {\n updateAccountReputation(_account);\n return _currentDelinquencies[_account].values();\n }\n\n function getCurrentDefaultLoanIds(address _account)\n public\n override\n returns (uint256[] memory)\n {\n updateAccountReputation(_account);\n return _currentDefaults[_account].values();\n }\n\n function updateAccountReputation(address _account) public override {\n uint256[] memory activeBidIds = tellerV2.getBorrowerActiveLoanIds(\n _account\n );\n for (uint256 i; i < activeBidIds.length; i++) {\n _applyReputation(_account, activeBidIds[i]);\n }\n }\n\n function updateAccountReputation(address _account, uint256 _bidId)\n public\n override\n returns (RepMark)\n {\n return _applyReputation(_account, _bidId);\n }\n\n function _applyReputation(address _account, uint256 _bidId)\n internal\n returns (RepMark mark_)\n {\n mark_ = RepMark.Good;\n\n if (tellerV2.isLoanDefaulted(_bidId)) {\n mark_ = RepMark.Default;\n\n // Remove delinquent status\n _removeMark(_account, _bidId, RepMark.Delinquent);\n } else if (tellerV2.isPaymentLate(_bidId)) {\n mark_ = RepMark.Delinquent;\n }\n\n // Mark status if not \"Good\"\n if (mark_ != RepMark.Good) {\n _addMark(_account, _bidId, mark_);\n }\n }\n\n function _addMark(address _account, uint256 _bidId, RepMark _mark)\n internal\n {\n if (_mark == RepMark.Delinquent) {\n _delinquencies[_account].add(_bidId);\n _currentDelinquencies[_account].add(_bidId);\n } else if (_mark == RepMark.Default) {\n _defaults[_account].add(_bidId);\n _currentDefaults[_account].add(_bidId);\n }\n\n emit MarkAdded(_account, _mark, _bidId);\n }\n\n function _removeMark(address _account, uint256 _bidId, RepMark _mark)\n internal\n {\n if (_mark == RepMark.Delinquent) {\n _currentDelinquencies[_account].remove(_bidId);\n } else if (_mark == RepMark.Default) {\n _currentDefaults[_account].remove(_bidId);\n }\n\n emit MarkRemoved(_account, _mark, _bidId);\n }\n}\n" + }, + "contracts/TellerV2.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// Contracts\nimport \"./ProtocolFee.sol\";\nimport \"./TellerV2Storage.sol\";\nimport \"./TellerV2Context.sol\";\nimport \"./pausing/HasProtocolPausingManager.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\"; \nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\";\n\n// Interfaces\nimport \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/IReputationManager.sol\";\nimport \"./interfaces/ITellerV2.sol\";\nimport { Collateral } from \"./interfaces/escrow/ICollateralEscrowV1.sol\";\nimport \"./interfaces/IEscrowVault.sol\";\n\nimport { ILoanRepaymentCallbacks } from \"./interfaces/ILoanRepaymentCallbacks.sol\";\nimport \"./interfaces/ILoanRepaymentListener.sol\";\n\n// Libraries\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"./libraries/NumbersLib.sol\";\n\nimport { V2Calculations, PaymentCycleType } from \"./libraries/V2Calculations.sol\";\n\n/* Errors */\n/**\n * @notice This error is reverted when the action isn't allowed\n * @param bidId The id of the bid.\n * @param action The action string (i.e: 'repayLoan', 'cancelBid', 'etc)\n * @param message The message string to return to the user explaining why the tx was reverted\n */\nerror ActionNotAllowed(uint256 bidId, string action, string message);\n\n/**\n * @notice This error is reverted when repayment amount is less than the required minimum\n * @param bidId The id of the bid the borrower is attempting to repay.\n * @param payment The payment made by the borrower\n * @param minimumOwed The minimum owed value\n */\nerror PaymentNotMinimum(uint256 bidId, uint256 payment, uint256 minimumOwed);\n\ncontract TellerV2 is\n ITellerV2,\n ILoanRepaymentCallbacks,\n OwnableUpgradeable,\n ProtocolFee,\n HasProtocolPausingManager,\n TellerV2Storage,\n TellerV2Context\n{\n using Address for address;\n using SafeERC20 for IERC20;\n using NumbersLib for uint256;\n using EnumerableSet for EnumerableSet.AddressSet;\n using EnumerableSet for EnumerableSet.UintSet;\n\n //the first 20 bytes of keccak256(\"lender manager\")\n address constant USING_LENDER_MANAGER =\n 0x84D409EeD89F6558fE3646397146232665788bF8;\n\n /** Events */\n\n /**\n * @notice This event is emitted when a new bid is submitted.\n * @param bidId The id of the bid submitted.\n * @param borrower The address of the bid borrower.\n * @param metadataURI URI for additional bid information as part of loan bid.\n */\n event SubmittedBid(\n uint256 indexed bidId,\n address indexed borrower,\n address receiver,\n bytes32 indexed metadataURI\n );\n\n /**\n * @notice This event is emitted when a bid has been accepted by a lender.\n * @param bidId The id of the bid accepted.\n * @param lender The address of the accepted bid lender.\n */\n event AcceptedBid(uint256 indexed bidId, address indexed lender);\n\n /**\n * @notice This event is emitted when a previously submitted bid has been cancelled.\n * @param bidId The id of the cancelled bid.\n */\n event CancelledBid(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when market owner has cancelled a pending bid in their market.\n * @param bidId The id of the bid funded.\n *\n * Note: The `CancelledBid` event will also be emitted.\n */\n event MarketOwnerCancelledBid(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when a payment is made towards an active loan.\n * @param bidId The id of the bid/loan to which the payment was made.\n */\n event LoanRepayment(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when a loan has been fully repaid.\n * @param bidId The id of the bid/loan which was repaid.\n */\n event LoanRepaid(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when a loan has been closed by a lender to claim collateral.\n * @param bidId The id of the bid accepted.\n */\n event LoanClosed(uint256 indexed bidId);\n\n /**\n * @notice This event is emitted when a loan has been fully repaid.\n * @param bidId The id of the bid/loan which was repaid.\n */\n event LoanLiquidated(uint256 indexed bidId, address indexed liquidator);\n\n /**\n * @notice This event is emitted when a fee has been paid related to a bid.\n * @param bidId The id of the bid.\n * @param feeType The name of the fee being paid.\n * @param amount The amount of the fee being paid.\n */\n event FeePaid(\n uint256 indexed bidId,\n string indexed feeType,\n uint256 indexed amount\n );\n\n /** Modifiers */\n\n /**\n * @notice This modifier is used to check if the state of a bid is pending, before running an action.\n * @param _bidId The id of the bid to check the state for.\n * @param _action The desired action to run on the bid.\n */\n modifier pendingBid(uint256 _bidId, string memory _action) {\n if (bids[_bidId].state != BidState.PENDING) {\n revert ActionNotAllowed(_bidId, _action, \"Bid not pending\");\n }\n\n _;\n }\n\n /**\n * @notice This modifier is used to check if the state of a loan has been accepted, before running an action.\n * @param _bidId The id of the bid to check the state for.\n * @param _action The desired action to run on the bid.\n */\n modifier acceptedLoan(uint256 _bidId, string memory _action) {\n if (bids[_bidId].state != BidState.ACCEPTED) {\n revert ActionNotAllowed(_bidId, _action, \"Loan not accepted\");\n }\n\n _;\n }\n\n\n /** Constant Variables **/\n\n uint8 public constant CURRENT_CODE_VERSION = 10;\n\n uint32 public constant LIQUIDATION_DELAY = 86400; //ONE DAY IN SECONDS\n\n /** Constructor **/\n\n constructor(address trustedForwarder) TellerV2Context(trustedForwarder) {}\n\n /** External Functions **/\n\n /**\n * @notice Initializes the proxy.\n * @param _protocolFee The fee collected by the protocol for loan processing.\n * @param _marketRegistry The address of the market registry contract for the protocol.\n * @param _reputationManager The address of the reputation manager contract.\n * @param _lenderCommitmentForwarder The address of the lender commitment forwarder contract.\n * @param _collateralManager The address of the collateral manager contracts.\n * @param _lenderManager The address of the lender manager contract for loans on the protocol.\n * @param _protocolPausingManager The address of the pausing manager contract for the protocol.\n */\n function initialize(\n uint16 _protocolFee,\n address _marketRegistry,\n address _reputationManager,\n address _lenderCommitmentForwarder,\n address _collateralManager,\n address _lenderManager,\n address _escrowVault,\n address _protocolPausingManager\n ) external initializer {\n __ProtocolFee_init(_protocolFee);\n\n //__Pausable_init();\n\n require(\n _lenderCommitmentForwarder.isContract(),\n \"LCF_ic\"\n );\n lenderCommitmentForwarder = _lenderCommitmentForwarder;\n\n require(\n _marketRegistry.isContract(),\n \"MR_ic\"\n );\n marketRegistry = IMarketRegistry(_marketRegistry);\n\n require(\n _reputationManager.isContract(),\n \"RM_ic\"\n );\n reputationManager = IReputationManager(_reputationManager);\n\n require(\n _collateralManager.isContract(),\n \"CM_ic\"\n );\n collateralManager = ICollateralManager(_collateralManager);\n\n \n \n require(\n _lenderManager.isContract(),\n \"LM_ic\"\n );\n lenderManager = ILenderManager(_lenderManager);\n\n\n \n\n require(_escrowVault.isContract(), \"EV_ic\");\n escrowVault = IEscrowVault(_escrowVault);\n\n\n\n\n _setProtocolPausingManager(_protocolPausingManager);\n }\n\n\n /* function setEscrowVault(address _escrowVault) external reinitializer(9) {\n _setEscrowVault(_escrowVault);\n }\n */\n\n\n function setProtocolPausingManager( \n address _protocolPausingManager\n ) external onlyOwner reinitializer(10) {\n\n _setProtocolPausingManager(_protocolPausingManager);\n\n }\n \n \n /**\n * @notice Function for a borrower to create a bid for a loan without Collateral.\n * @param _lendingToken The lending token asset requested to be borrowed.\n * @param _marketplaceId The unique id of the marketplace for the bid.\n * @param _principal The principal amount of the loan bid.\n * @param _duration The recurrent length of time before which a payment is due.\n * @param _APR The proposed interest rate for the loan bid.\n * @param _metadataURI The URI for additional borrower loan information as part of loan bid.\n * @param _receiver The address where the loan amount will be sent to.\n */\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver\n ) public override whenProtocolNotPaused returns (uint256 bidId_) {\n bidId_ = _submitBid(\n _lendingToken,\n _marketplaceId,\n _principal,\n _duration,\n _APR,\n _metadataURI,\n _receiver\n );\n }\n\n /**\n * @notice Function for a borrower to create a bid for a loan with Collateral.\n * @param _lendingToken The lending token asset requested to be borrowed.\n * @param _marketplaceId The unique id of the marketplace for the bid.\n * @param _principal The principal amount of the loan bid.\n * @param _duration The recurrent length of time before which a payment is due.\n * @param _APR The proposed interest rate for the loan bid.\n * @param _metadataURI The URI for additional borrower loan information as part of loan bid.\n * @param _receiver The address where the loan amount will be sent to.\n * @param _collateralInfo Additional information about the collateral asset.\n */\n function submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver,\n Collateral[] calldata _collateralInfo\n ) public override whenProtocolNotPaused returns (uint256 bidId_) {\n bidId_ = _submitBid(\n _lendingToken,\n _marketplaceId,\n _principal,\n _duration,\n _APR,\n _metadataURI,\n _receiver\n );\n\n bool validation = collateralManager.commitCollateral(\n bidId_,\n _collateralInfo\n );\n\n require(\n validation == true,\n \"C bal NV\"\n );\n }\n\n function _submitBid(\n address _lendingToken,\n uint256 _marketplaceId,\n uint256 _principal,\n uint32 _duration,\n uint16 _APR,\n string calldata _metadataURI,\n address _receiver\n ) internal virtual returns (uint256 bidId_) {\n address sender = _msgSenderForMarket(_marketplaceId);\n\n (bool isVerified, ) = marketRegistry.isVerifiedBorrower(\n _marketplaceId,\n sender\n );\n\n require(isVerified, \"Borrower NV\");\n\n require(\n marketRegistry.isMarketOpen(_marketplaceId),\n \"Mkt C\"\n );\n\n // Set response bid ID.\n bidId_ = bidId;\n\n // Create and store our bid into the mapping\n Bid storage bid = bids[bidId];\n bid.borrower = sender;\n bid.receiver = _receiver != address(0) ? _receiver : bid.borrower;\n bid.marketplaceId = _marketplaceId;\n bid.loanDetails.lendingToken = IERC20(_lendingToken);\n bid.loanDetails.principal = _principal;\n bid.loanDetails.loanDuration = _duration;\n bid.loanDetails.timestamp = uint32(block.timestamp);\n\n // Set payment cycle type based on market setting (custom or monthly)\n (bid.terms.paymentCycle, bidPaymentCycleType[bidId]) = marketRegistry\n .getPaymentCycle(_marketplaceId);\n\n bid.terms.APR = _APR;\n\n bidDefaultDuration[bidId] = marketRegistry.getPaymentDefaultDuration(\n _marketplaceId\n );\n\n bidExpirationTime[bidId] = marketRegistry.getBidExpirationTime(\n _marketplaceId\n );\n\n bid.paymentType = marketRegistry.getPaymentType(_marketplaceId);\n\n bid.terms.paymentCycleAmount = V2Calculations\n .calculatePaymentCycleAmount(\n bid.paymentType,\n bidPaymentCycleType[bidId],\n _principal,\n _duration,\n bid.terms.paymentCycle,\n _APR\n );\n\n uris[bidId] = _metadataURI;\n bid.state = BidState.PENDING;\n\n emit SubmittedBid(\n bidId,\n bid.borrower,\n bid.receiver,\n keccak256(abi.encodePacked(_metadataURI))\n );\n\n // Store bid inside borrower bids mapping\n borrowerBids[bid.borrower].push(bidId);\n\n // Increment bid id counter\n bidId++;\n }\n\n /**\n * @notice Function for a borrower to cancel their pending bid.\n * @param _bidId The id of the bid to cancel.\n */\n function cancelBid(uint256 _bidId) external {\n if (\n _msgSenderForMarket(bids[_bidId].marketplaceId) !=\n bids[_bidId].borrower\n ) {\n revert ActionNotAllowed({\n bidId: _bidId,\n action: \"cancelBid\",\n message: \"Not bid owner\" //this is a TON of storage space\n });\n }\n _cancelBid(_bidId);\n }\n\n /**\n * @notice Function for a market owner to cancel a bid in the market.\n * @param _bidId The id of the bid to cancel.\n */\n function marketOwnerCancelBid(uint256 _bidId) external {\n if (\n _msgSender() !=\n marketRegistry.getMarketOwner(bids[_bidId].marketplaceId)\n ) {\n revert ActionNotAllowed({\n bidId: _bidId,\n action: \"marketOwnerCancelBid\",\n message: \"Not market owner\" //this is a TON of storage space \n });\n }\n _cancelBid(_bidId);\n emit MarketOwnerCancelledBid(_bidId);\n }\n\n /**\n * @notice Function for users to cancel a bid.\n * @param _bidId The id of the bid to be cancelled.\n */\n function _cancelBid(uint256 _bidId)\n internal\n virtual\n pendingBid(_bidId, \"cancelBid\")\n {\n // Set the bid state to CANCELLED\n bids[_bidId].state = BidState.CANCELLED;\n\n // Emit CancelledBid event\n emit CancelledBid(_bidId);\n }\n\n /**\n * @notice Function for a lender to accept a proposed loan bid.\n * @param _bidId The id of the loan bid to accept.\n */\n function lenderAcceptBid(uint256 _bidId)\n external\n override\n pendingBid(_bidId, \"lenderAcceptBid\")\n whenProtocolNotPaused\n returns (\n uint256 amountToProtocol,\n uint256 amountToMarketplace,\n uint256 amountToBorrower\n )\n {\n // Retrieve bid\n Bid storage bid = bids[_bidId];\n\n address sender = _msgSenderForMarket(bid.marketplaceId);\n\n (bool isVerified, ) = marketRegistry.isVerifiedLender(\n bid.marketplaceId,\n sender\n );\n require(isVerified, \"NV\");\n\n require(\n !marketRegistry.isMarketClosed(bid.marketplaceId),\n \"Market is closed\"\n );\n\n require(!isLoanExpired(_bidId), \"BE\");\n\n // Set timestamp\n bid.loanDetails.acceptedTimestamp = uint32(block.timestamp);\n bid.loanDetails.lastRepaidTimestamp = uint32(block.timestamp);\n\n // Mark borrower's request as accepted\n bid.state = BidState.ACCEPTED;\n\n // Declare the bid acceptor as the lender of the bid\n bid.lender = sender;\n\n // Tell the collateral manager to deploy the escrow and pull funds from the borrower if applicable\n collateralManager.deployAndDeposit(_bidId);\n\n // Transfer funds to borrower from the lender\n amountToProtocol = bid.loanDetails.principal.percent(protocolFee());\n amountToMarketplace = bid.loanDetails.principal.percent(\n marketRegistry.getMarketplaceFee(bid.marketplaceId)\n );\n amountToBorrower =\n bid.loanDetails.principal -\n amountToProtocol -\n amountToMarketplace;\n\n //transfer fee to protocol\n if (amountToProtocol > 0) {\n bid.loanDetails.lendingToken.safeTransferFrom(\n sender,\n owner(),\n amountToProtocol\n );\n }\n\n //transfer fee to marketplace\n if (amountToMarketplace > 0) {\n bid.loanDetails.lendingToken.safeTransferFrom(\n sender,\n marketRegistry.getMarketFeeRecipient(bid.marketplaceId),\n amountToMarketplace\n );\n }\n\n //transfer funds to borrower\n if (amountToBorrower > 0) {\n bid.loanDetails.lendingToken.safeTransferFrom(\n sender,\n bid.receiver,\n amountToBorrower\n );\n }\n\n // Record volume filled by lenders\n lenderVolumeFilled[address(bid.loanDetails.lendingToken)][sender] += bid\n .loanDetails\n .principal;\n totalVolumeFilled[address(bid.loanDetails.lendingToken)] += bid\n .loanDetails\n .principal;\n\n // Add borrower's active bid\n _borrowerBidsActive[bid.borrower].add(_bidId);\n\n // Emit AcceptedBid\n emit AcceptedBid(_bidId, sender);\n\n emit FeePaid(_bidId, \"protocol\", amountToProtocol);\n emit FeePaid(_bidId, \"marketplace\", amountToMarketplace);\n }\n\n function claimLoanNFT(uint256 _bidId)\n external\n acceptedLoan(_bidId, \"claimLoanNFT\")\n whenProtocolNotPaused\n {\n // Retrieve bid\n Bid storage bid = bids[_bidId];\n\n address sender = _msgSenderForMarket(bid.marketplaceId);\n require(sender == bid.lender, \"NV Lender\");\n\n // set lender address to the lender manager so we know to check the owner of the NFT for the true lender\n bid.lender = address(USING_LENDER_MANAGER);\n\n // mint an NFT with the lender manager\n lenderManager.registerLoan(_bidId, sender);\n }\n\n /**\n * @notice Function for users to make the minimum amount due for an active loan.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanMinimum(uint256 _bidId)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n (\n uint256 owedPrincipal,\n uint256 duePrincipal,\n uint256 interest\n ) = V2Calculations.calculateAmountOwed(\n bids[_bidId],\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n _repayLoan(\n _bidId,\n Payment({ principal: duePrincipal, interest: interest }),\n owedPrincipal + interest,\n true\n );\n }\n\n /**\n * @notice Function for users to repay an active loan in full.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanFull(uint256 _bidId)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n _repayLoanFull(_bidId, true);\n }\n\n // function that the borrower (ideally) sends to repay the loan\n /**\n * @notice Function for users to make a payment towards an active loan.\n * @param _bidId The id of the loan to make the payment towards.\n * @param _amount The amount of the payment.\n */\n function repayLoan(uint256 _bidId, uint256 _amount)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n _repayLoanAtleastMinimum(_bidId, _amount, true);\n }\n\n /**\n * @notice Function for users to repay an active loan in full.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function repayLoanFullWithoutCollateralWithdraw(uint256 _bidId)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n _repayLoanFull(_bidId, false);\n }\n\n function repayLoanWithoutCollateralWithdraw(uint256 _bidId, uint256 _amount)\n external\n acceptedLoan(_bidId, \"repayLoan\")\n {\n _repayLoanAtleastMinimum(_bidId, _amount, false);\n }\n\n function _repayLoanFull(uint256 _bidId, bool withdrawCollateral) internal {\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bids[_bidId],\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n _repayLoan(\n _bidId,\n Payment({ principal: owedPrincipal, interest: interest }),\n owedPrincipal + interest,\n withdrawCollateral\n );\n }\n\n function _repayLoanAtleastMinimum(\n uint256 _bidId,\n uint256 _amount,\n bool withdrawCollateral\n ) internal {\n (\n uint256 owedPrincipal,\n uint256 duePrincipal,\n uint256 interest\n ) = V2Calculations.calculateAmountOwed(\n bids[_bidId],\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n uint256 minimumOwed = duePrincipal + interest;\n\n // If amount is less than minimumOwed, we revert\n if (_amount < minimumOwed) {\n revert PaymentNotMinimum(_bidId, _amount, minimumOwed);\n }\n\n _repayLoan(\n _bidId,\n Payment({ principal: _amount - interest, interest: interest }),\n owedPrincipal + interest,\n withdrawCollateral\n );\n }\n\n \n\n\n function lenderCloseLoan(uint256 _bidId)\n external whenProtocolNotPaused whenLiquidationsNotPaused\n acceptedLoan(_bidId, \"lenderClaimCollateral\")\n {\n Bid storage bid = bids[_bidId];\n address _collateralRecipient = getLoanLender(_bidId);\n\n _lenderCloseLoanWithRecipient(_bidId, _collateralRecipient);\n }\n\n /**\n * @notice Function for lender to claim collateral for a defaulted loan. The only purpose of a CLOSED loan is to make collateral claimable by lender.\n * @param _bidId The id of the loan to set to CLOSED status.\n */\n function lenderCloseLoanWithRecipient(\n uint256 _bidId,\n address _collateralRecipient\n ) external whenProtocolNotPaused whenLiquidationsNotPaused {\n _lenderCloseLoanWithRecipient(_bidId, _collateralRecipient);\n }\n\n function _lenderCloseLoanWithRecipient(\n uint256 _bidId,\n address _collateralRecipient\n ) internal acceptedLoan(_bidId, \"lenderClaimCollateral\") {\n require(isLoanDefaulted(_bidId), \"ND\");\n\n Bid storage bid = bids[_bidId];\n bid.state = BidState.CLOSED;\n\n address sender = _msgSenderForMarket(bid.marketplaceId);\n require(sender == getLoanLender(_bidId), \"NLL\");\n\n \n collateralManager.lenderClaimCollateralWithRecipient(_bidId, _collateralRecipient);\n\n emit LoanClosed(_bidId);\n }\n\n /**\n * @notice Function for users to liquidate a defaulted loan.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function liquidateLoanFull(uint256 _bidId)\n external whenProtocolNotPaused whenLiquidationsNotPaused\n acceptedLoan(_bidId, \"liquidateLoan\")\n {\n Bid storage bid = bids[_bidId];\n\n // If loan is backed by collateral, withdraw and send to the liquidator\n address recipient = _msgSenderForMarket(bid.marketplaceId);\n\n _liquidateLoanFull(_bidId, recipient);\n }\n\n function liquidateLoanFullWithRecipient(uint256 _bidId, address _recipient)\n external whenProtocolNotPaused whenLiquidationsNotPaused\n acceptedLoan(_bidId, \"liquidateLoan\")\n {\n _liquidateLoanFull(_bidId, _recipient);\n }\n\n /**\n * @notice Function for users to liquidate a defaulted loan.\n * @param _bidId The id of the loan to make the payment towards.\n */\n function _liquidateLoanFull(uint256 _bidId, address _recipient)\n internal\n acceptedLoan(_bidId, \"liquidateLoan\")\n {\n require(isLoanLiquidateable(_bidId), \"NL\");\n\n Bid storage bid = bids[_bidId];\n\n // change state here to prevent re-entrancy\n bid.state = BidState.LIQUIDATED;\n\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bid,\n block.timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n\n //this sets the state to 'repaid'\n _repayLoan(\n _bidId,\n Payment({ principal: owedPrincipal, interest: interest }),\n owedPrincipal + interest,\n false\n );\n\n collateralManager.liquidateCollateral(_bidId, _recipient);\n\n address liquidator = _msgSenderForMarket(bid.marketplaceId);\n\n emit LoanLiquidated(_bidId, liquidator);\n }\n\n /**\n * @notice Internal function to make a loan payment.\n * @dev Updates the bid's `status` to `PAID` only if it is not already marked as `LIQUIDATED`\n * @param _bidId The id of the loan to make the payment towards.\n * @param _payment The Payment struct with payments amounts towards principal and interest respectively.\n * @param _owedAmount The total amount owed on the loan.\n */\n function _repayLoan(\n uint256 _bidId,\n Payment memory _payment,\n uint256 _owedAmount,\n bool _shouldWithdrawCollateral\n ) internal virtual {\n Bid storage bid = bids[_bidId];\n uint256 paymentAmount = _payment.principal + _payment.interest;\n\n RepMark mark = reputationManager.updateAccountReputation(\n bid.borrower,\n _bidId\n );\n\n // Check if we are sending a payment or amount remaining\n if (paymentAmount >= _owedAmount) {\n paymentAmount = _owedAmount;\n\n if (bid.state != BidState.LIQUIDATED) {\n bid.state = BidState.PAID;\n }\n\n // Remove borrower's active bid\n _borrowerBidsActive[bid.borrower].remove(_bidId);\n\n // If loan is is being liquidated and backed by collateral, withdraw and send to borrower\n if (_shouldWithdrawCollateral) { \n \n // _getCollateralManagerForBid(_bidId).withdraw(_bidId);\n collateralManager.withdraw(_bidId);\n }\n\n emit LoanRepaid(_bidId);\n } else {\n emit LoanRepayment(_bidId);\n }\n\n _sendOrEscrowFunds(_bidId, _payment); //send or escrow the funds\n\n // update our mappings\n bid.loanDetails.totalRepaid.principal += _payment.principal;\n bid.loanDetails.totalRepaid.interest += _payment.interest;\n bid.loanDetails.lastRepaidTimestamp = uint32(block.timestamp);\n\n // If the loan is paid in full and has a mark, we should update the current reputation\n if (mark != RepMark.Good) {\n reputationManager.updateAccountReputation(bid.borrower, _bidId);\n }\n }\n\n\n function _sendOrEscrowFunds(uint256 _bidId, Payment memory _payment)\n internal\n {\n Bid storage bid = bids[_bidId];\n address lender = getLoanLender(_bidId);\n\n uint256 _paymentAmount = _payment.principal + _payment.interest;\n\n try \n\n bid.loanDetails.lendingToken.transferFrom{ gas: 100000 }(\n _msgSenderForMarket(bid.marketplaceId),\n lender,\n _paymentAmount\n )\n {} catch {\n address sender = _msgSenderForMarket(bid.marketplaceId);\n\n uint256 balanceBefore = bid.loanDetails.lendingToken.balanceOf(\n address(this)\n ); \n\n //if unable, pay to escrow\n bid.loanDetails.lendingToken.safeTransferFrom(\n sender,\n address(this),\n _paymentAmount\n );\n\n uint256 balanceAfter = bid.loanDetails.lendingToken.balanceOf(\n address(this)\n );\n\n //used for fee-on-send tokens\n uint256 paymentAmountReceived = balanceAfter - balanceBefore;\n\n bid.loanDetails.lendingToken.approve(\n address(escrowVault),\n paymentAmountReceived\n );\n\n IEscrowVault(escrowVault).deposit(\n lender,\n address(bid.loanDetails.lendingToken),\n paymentAmountReceived\n );\n }\n\n address loanRepaymentListener = repaymentListenerForBid[_bidId];\n\n if (loanRepaymentListener != address(0)) {\n require(gasleft() >= 80000, \"NR gas\"); //fixes the 63/64 remaining issue\n try\n ILoanRepaymentListener(loanRepaymentListener).repayLoanCallback{\n gas: 80000\n }( //limit gas costs to prevent lender preventing repayments\n _bidId,\n _msgSenderForMarket(bid.marketplaceId),\n _payment.principal,\n _payment.interest\n )\n {} catch {}\n }\n }\n\n\n\n\n /**\n * @notice Calculates the total amount owed for a loan bid at a specific timestamp.\n * @param _bidId The id of the loan bid to calculate the owed amount for.\n * @param _timestamp The timestamp at which to calculate the loan owed amount at.\n */\n function calculateAmountOwed(uint256 _bidId, uint256 _timestamp)\n public\n view\n returns (Payment memory owed)\n {\n Bid storage bid = bids[_bidId];\n if (\n bid.state != BidState.ACCEPTED ||\n bid.loanDetails.acceptedTimestamp >= _timestamp\n ) return owed;\n\n (uint256 owedPrincipal, , uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bid,\n _timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n\n owed.principal = owedPrincipal;\n owed.interest = interest;\n }\n\n /**\n * @notice Calculates the minimum payment amount due for a loan at a specific timestamp.\n * @param _bidId The id of the loan bid to get the payment amount for.\n * @param _timestamp The timestamp at which to get the due payment at.\n */\n function calculateAmountDue(uint256 _bidId, uint256 _timestamp)\n public\n view\n returns (Payment memory due)\n {\n Bid storage bid = bids[_bidId];\n if (\n bids[_bidId].state != BidState.ACCEPTED ||\n bid.loanDetails.acceptedTimestamp >= _timestamp\n ) return due;\n\n (, uint256 duePrincipal, uint256 interest) = V2Calculations\n .calculateAmountOwed(\n bid,\n _timestamp,\n _getBidPaymentCycleType(_bidId),\n _getBidPaymentCycleDuration(_bidId)\n );\n due.principal = duePrincipal;\n due.interest = interest;\n }\n\n /**\n * @notice Returns the next due date for a loan payment.\n * @param _bidId The id of the loan bid.\n */\n function calculateNextDueDate(uint256 _bidId)\n public\n view\n returns (uint32 dueDate_)\n {\n Bid storage bid = bids[_bidId];\n if (bids[_bidId].state != BidState.ACCEPTED) return dueDate_;\n\n return\n V2Calculations.calculateNextDueDate(\n bid.loanDetails.acceptedTimestamp,\n bid.terms.paymentCycle,\n bid.loanDetails.loanDuration,\n lastRepaidTimestamp(_bidId),\n bidPaymentCycleType[_bidId]\n );\n }\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n */\n function isPaymentLate(uint256 _bidId) public view override returns (bool) {\n if (bids[_bidId].state != BidState.ACCEPTED) return false;\n return uint32(block.timestamp) > calculateNextDueDate(_bidId);\n }\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n * @return bool True if the loan is defaulted.\n */\n function isLoanDefaulted(uint256 _bidId)\n public\n view\n override\n returns (bool)\n {\n return _isLoanDefaulted(_bidId, 0);\n }\n\n /**\n * @notice Checks to see if a loan was delinquent for longer than liquidation delay.\n * @param _bidId The id of the loan bid to check for.\n * @return bool True if the loan is liquidateable.\n */\n function isLoanLiquidateable(uint256 _bidId)\n public\n view\n override\n returns (bool)\n {\n return _isLoanDefaulted(_bidId, LIQUIDATION_DELAY);\n }\n\n /**\n * @notice Checks to see if a borrower is delinquent.\n * @param _bidId The id of the loan bid to check for.\n * @param _additionalDelay Amount of additional seconds after a loan defaulted to allow a liquidation.\n * @return bool True if the loan is liquidateable.\n */\n function _isLoanDefaulted(uint256 _bidId, uint32 _additionalDelay)\n internal\n view\n returns (bool)\n {\n Bid storage bid = bids[_bidId];\n\n // Make sure loan cannot be liquidated if it is not active\n if (bid.state != BidState.ACCEPTED) return false;\n\n uint32 defaultDuration = bidDefaultDuration[_bidId];\n\n uint32 dueDate = calculateNextDueDate(_bidId);\n\n return\n uint32(block.timestamp) >\n dueDate + defaultDuration + _additionalDelay;\n }\n\n function getEscrowVault() external view returns(address){\n return address(escrowVault);\n }\n\n function getBidState(uint256 _bidId)\n external\n view\n override\n returns (BidState)\n {\n return bids[_bidId].state;\n }\n\n function getBorrowerActiveLoanIds(address _borrower)\n external\n view\n override\n returns (uint256[] memory)\n {\n return _borrowerBidsActive[_borrower].values();\n }\n\n function getBorrowerLoanIds(address _borrower)\n external\n view\n returns (uint256[] memory)\n {\n return borrowerBids[_borrower];\n }\n\n /**\n * @notice Checks to see if a pending loan has expired so it is no longer able to be accepted.\n * @param _bidId The id of the loan bid to check for.\n */\n function isLoanExpired(uint256 _bidId) public view returns (bool) {\n Bid storage bid = bids[_bidId];\n\n if (bid.state != BidState.PENDING) return false;\n if (bidExpirationTime[_bidId] == 0) return false;\n\n return (uint32(block.timestamp) >\n bid.loanDetails.timestamp + bidExpirationTime[_bidId]);\n }\n\n /**\n * @notice Returns the last repaid timestamp for a loan.\n * @param _bidId The id of the loan bid to get the timestamp for.\n */\n function lastRepaidTimestamp(uint256 _bidId) public view returns (uint32) {\n return V2Calculations.lastRepaidTimestamp(bids[_bidId]);\n }\n\n /**\n * @notice Returns the borrower address for a given bid.\n * @param _bidId The id of the bid/loan to get the borrower for.\n * @return borrower_ The address of the borrower associated with the bid.\n */\n function getLoanBorrower(uint256 _bidId)\n public\n view\n returns (address borrower_)\n {\n borrower_ = bids[_bidId].borrower;\n }\n\n /**\n * @notice Returns the lender address for a given bid. If the stored lender address is the `LenderManager` NFT address, return the `ownerOf` for the bid ID.\n * @param _bidId The id of the bid/loan to get the lender for.\n * @return lender_ The address of the lender associated with the bid.\n */\n function getLoanLender(uint256 _bidId)\n public\n view\n returns (address lender_)\n {\n lender_ = bids[_bidId].lender;\n\n if (lender_ == address(USING_LENDER_MANAGER)) {\n return lenderManager.ownerOf(_bidId);\n }\n\n //this is left in for backwards compatibility only\n if (lender_ == address(lenderManager)) {\n return lenderManager.ownerOf(_bidId);\n }\n }\n\n function getLoanLendingToken(uint256 _bidId)\n external\n view\n returns (address token_)\n {\n token_ = address(bids[_bidId].loanDetails.lendingToken);\n }\n\n function getLoanMarketId(uint256 _bidId)\n external\n view\n returns (uint256 _marketId)\n {\n _marketId = bids[_bidId].marketplaceId;\n }\n\n function getLoanSummary(uint256 _bidId)\n external\n view\n returns (\n address borrower,\n address lender,\n uint256 marketId,\n address principalTokenAddress,\n uint256 principalAmount,\n uint32 acceptedTimestamp,\n uint32 lastRepaidTimestamp,\n BidState bidState\n )\n {\n Bid storage bid = bids[_bidId];\n\n borrower = bid.borrower;\n lender = getLoanLender(_bidId);\n marketId = bid.marketplaceId;\n principalTokenAddress = address(bid.loanDetails.lendingToken);\n principalAmount = bid.loanDetails.principal;\n acceptedTimestamp = bid.loanDetails.acceptedTimestamp;\n lastRepaidTimestamp = V2Calculations.lastRepaidTimestamp(bids[_bidId]);\n bidState = bid.state;\n }\n\n // Additions for lender groups\n\n function getLoanDefaultTimestamp(uint256 _bidId)\n public\n view\n returns (uint256)\n {\n Bid storage bid = bids[_bidId];\n\n uint32 defaultDuration = _getBidDefaultDuration(_bidId);\n\n uint32 dueDate = calculateNextDueDate(_bidId);\n\n return dueDate + defaultDuration;\n }\n \n function setRepaymentListenerForBid(uint256 _bidId, address _listener) external {\n uint256 codeSize;\n assembly {\n codeSize := extcodesize(_listener) \n }\n require(codeSize > 0, \"Not a contract\");\n address sender = _msgSenderForMarket(bids[_bidId].marketplaceId);\n\n require(\n sender == getLoanLender(_bidId),\n \"Not lender\"\n );\n\n repaymentListenerForBid[_bidId] = _listener;\n }\n\n\n\n\n function getRepaymentListenerForBid(uint256 _bidId)\n external\n view\n returns (address)\n {\n return repaymentListenerForBid[_bidId];\n }\n\n // ----------\n\n function _getBidPaymentCycleType(uint256 _bidId)\n internal\n view\n returns (PaymentCycleType)\n {\n \n\n return bidPaymentCycleType[_bidId];\n }\n\n function _getBidPaymentCycleDuration(uint256 _bidId)\n internal\n view\n returns (uint32)\n {\n \n\n Bid storage bid = bids[_bidId];\n\n return bid.terms.paymentCycle;\n }\n\n function _getBidDefaultDuration(uint256 _bidId)\n internal\n view\n returns (uint32)\n {\n \n\n return bidDefaultDuration[_bidId];\n }\n\n // -----\n\n /** OpenZeppelin Override Functions **/\n\n function _msgSender()\n internal\n view\n virtual\n override(ERC2771ContextUpgradeable, ContextUpgradeable)\n returns (address sender)\n {\n sender = ERC2771ContextUpgradeable._msgSender();\n }\n\n function _msgData()\n internal\n view\n virtual\n override(ERC2771ContextUpgradeable, ContextUpgradeable)\n returns (bytes calldata)\n {\n return ERC2771ContextUpgradeable._msgData();\n }\n}\n" + }, + "contracts/TellerV2Autopay.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./interfaces/ITellerV2.sol\";\nimport \"./interfaces/ITellerV2Autopay.sol\";\n\nimport \"./libraries/NumbersLib.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport { Payment } from \"./TellerV2Storage.sol\";\n\n/**\n * @dev Helper contract to autopay loans\n */\ncontract TellerV2Autopay is OwnableUpgradeable, ITellerV2Autopay {\n using SafeERC20 for ERC20;\n using NumbersLib for uint256;\n\n ITellerV2 public immutable tellerV2;\n\n //bidId => enabled\n mapping(uint256 => bool) public loanAutoPayEnabled;\n\n // Autopay fee set for automatic loan payments\n uint16 private _autopayFee;\n\n /**\n * @notice This event is emitted when a loan is autopaid.\n * @param bidId The id of the bid/loan which was repaid.\n * @param msgsender The account that called the method\n */\n event AutoPaidLoanMinimum(uint256 indexed bidId, address indexed msgsender);\n\n /**\n * @notice This event is emitted when loan autopayments are enabled or disabled.\n * @param bidId The id of the bid/loan.\n * @param enabled Whether the autopayments are enabled or disabled\n */\n event AutoPayEnabled(uint256 indexed bidId, bool enabled);\n\n /**\n * @notice This event is emitted when the autopay fee has been updated.\n * @param newFee The new autopay fee set.\n * @param oldFee The previously set autopay fee.\n */\n event AutopayFeeSet(uint16 newFee, uint16 oldFee);\n\n constructor(address _protocolAddress) {\n tellerV2 = ITellerV2(_protocolAddress);\n }\n\n /**\n * @notice Initialized the proxy.\n * @param _fee The fee collected for automatic payment processing.\n * @param _owner The address of the ownership to be transferred to.\n */\n function initialize(uint16 _fee, address _owner) external initializer {\n _transferOwnership(_owner);\n _setAutopayFee(_fee);\n }\n\n /**\n * @notice Let the owner of the contract set a new autopay fee.\n * @param _newFee The new autopay fee to set.\n */\n function setAutopayFee(uint16 _newFee) public virtual onlyOwner {\n _setAutopayFee(_newFee);\n }\n\n function _setAutopayFee(uint16 _newFee) internal {\n // Skip if the fee is the same\n if (_newFee == _autopayFee) return;\n uint16 oldFee = _autopayFee;\n _autopayFee = _newFee;\n emit AutopayFeeSet(_newFee, oldFee);\n }\n\n /**\n * @notice Returns the current autopay fee.\n */\n function getAutopayFee() public view virtual returns (uint16) {\n return _autopayFee;\n }\n\n /**\n * @notice Function for a borrower to enable or disable autopayments\n * @param _bidId The id of the bid to cancel.\n * @param _autoPayEnabled boolean for allowing autopay on a loan\n */\n function setAutoPayEnabled(uint256 _bidId, bool _autoPayEnabled) external {\n require(\n _msgSender() == tellerV2.getLoanBorrower(_bidId),\n \"Only the borrower can set autopay\"\n );\n\n loanAutoPayEnabled[_bidId] = _autoPayEnabled;\n\n emit AutoPayEnabled(_bidId, _autoPayEnabled);\n }\n\n /**\n * @notice Function for a minimum autopayment to be performed on a loan\n * @param _bidId The id of the bid to repay.\n */\n function autoPayLoanMinimum(uint256 _bidId) external {\n require(\n loanAutoPayEnabled[_bidId],\n \"Autopay is not enabled for that loan\"\n );\n\n address lendingToken = ITellerV2(tellerV2).getLoanLendingToken(_bidId);\n address borrower = ITellerV2(tellerV2).getLoanBorrower(_bidId);\n\n uint256 amountToRepayMinimum = getEstimatedMinimumPayment(\n _bidId,\n block.timestamp\n );\n uint256 autopayFeeAmount = amountToRepayMinimum.percent(\n getAutopayFee()\n );\n\n // Pull lendingToken in from the borrower to this smart contract\n ERC20(lendingToken).safeTransferFrom(\n borrower,\n address(this),\n amountToRepayMinimum + autopayFeeAmount\n );\n\n // Transfer fee to msg sender\n ERC20(lendingToken).safeTransfer(_msgSender(), autopayFeeAmount);\n\n // Approve the lendingToken to tellerV2\n ERC20(lendingToken).approve(address(tellerV2), amountToRepayMinimum);\n\n // Use that lendingToken to repay the loan\n tellerV2.repayLoan(_bidId, amountToRepayMinimum);\n\n emit AutoPaidLoanMinimum(_bidId, msg.sender);\n }\n\n function getEstimatedMinimumPayment(uint256 _bidId, uint256 _timestamp)\n public\n virtual\n returns (uint256 _amount)\n {\n Payment memory estimatedPayment = tellerV2.calculateAmountDue(\n _bidId,\n _timestamp\n );\n\n _amount = estimatedPayment.principal + estimatedPayment.interest;\n }\n}\n" + }, + "contracts/TellerV2Context.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./TellerV2Storage.sol\";\nimport \"./ERC2771ContextUpgradeable.sol\";\n\n/**\n * @dev This contract should not use any storage\n */\n\nabstract contract TellerV2Context is\n ERC2771ContextUpgradeable,\n TellerV2Storage\n{\n using EnumerableSet for EnumerableSet.AddressSet;\n\n event TrustedMarketForwarderSet(\n uint256 indexed marketId,\n address forwarder,\n address sender\n );\n event MarketForwarderApproved(\n uint256 indexed marketId,\n address indexed forwarder,\n address sender\n );\n event MarketForwarderRenounced(\n uint256 indexed marketId,\n address indexed forwarder,\n address sender\n );\n\n constructor(address trustedForwarder)\n ERC2771ContextUpgradeable(trustedForwarder)\n {}\n\n /**\n * @notice Checks if an address is a trusted forwarder contract for a given market.\n * @param _marketId An ID for a lending market.\n * @param _trustedMarketForwarder An address to check if is a trusted forwarder in the given market.\n * @return A boolean indicating the forwarder address is trusted in a market.\n */\n function isTrustedMarketForwarder(\n uint256 _marketId,\n address _trustedMarketForwarder\n ) public view returns (bool) {\n return\n _trustedMarketForwarders[_marketId] == _trustedMarketForwarder ||\n lenderCommitmentForwarder == _trustedMarketForwarder;\n }\n\n /**\n * @notice Checks if an account has approved a forwarder for a market.\n * @param _marketId An ID for a lending market.\n * @param _forwarder A forwarder contract address.\n * @param _account The address to verify set an approval.\n * @return A boolean indicating if an approval was set.\n */\n function hasApprovedMarketForwarder(\n uint256 _marketId,\n address _forwarder,\n address _account\n ) public view returns (bool) {\n return\n isTrustedMarketForwarder(_marketId, _forwarder) &&\n _approvedForwarderSenders[_forwarder].contains(_account);\n }\n\n /**\n * @notice Sets a trusted forwarder for a lending market.\n * @notice The caller must owner the market given. See {MarketRegistry}\n * @param _marketId An ID for a lending market.\n * @param _forwarder A forwarder contract address.\n */\n function setTrustedMarketForwarder(uint256 _marketId, address _forwarder)\n external\n {\n require(\n marketRegistry.getMarketOwner(_marketId) == _msgSender(),\n \"Caller must be the market owner\"\n );\n _trustedMarketForwarders[_marketId] = _forwarder;\n emit TrustedMarketForwarderSet(_marketId, _forwarder, _msgSender());\n }\n\n /**\n * @notice Approves a forwarder contract to use their address as a sender for a specific market.\n * @notice The forwarder given must be trusted by the market given.\n * @param _marketId An ID for a lending market.\n * @param _forwarder A forwarder contract address.\n */\n function approveMarketForwarder(uint256 _marketId, address _forwarder)\n external\n {\n require(\n isTrustedMarketForwarder(_marketId, _forwarder),\n \"Forwarder must be trusted by the market\"\n );\n _approvedForwarderSenders[_forwarder].add(_msgSender());\n emit MarketForwarderApproved(_marketId, _forwarder, _msgSender());\n }\n\n /**\n * @notice Renounces approval of a market forwarder\n * @param _marketId An ID for a lending market.\n * @param _forwarder A forwarder contract address.\n */\n function renounceMarketForwarder(uint256 _marketId, address _forwarder)\n external\n {\n if (_approvedForwarderSenders[_forwarder].contains(_msgSender())) {\n _approvedForwarderSenders[_forwarder].remove(_msgSender());\n emit MarketForwarderRenounced(_marketId, _forwarder, _msgSender());\n }\n }\n\n /**\n * @notice Retrieves the function caller address by checking the appended calldata if the _actual_ caller is a trusted forwarder.\n * @param _marketId An ID for a lending market.\n * @return sender The address to use as the function caller.\n */\n function _msgSenderForMarket(uint256 _marketId)\n internal\n view\n virtual\n returns (address)\n {\n if (\n msg.data.length >= 20 &&\n isTrustedMarketForwarder(_marketId, _msgSender())\n ) {\n address sender;\n assembly {\n sender := shr(96, calldataload(sub(calldatasize(), 20)))\n }\n // Ensure the appended sender address approved the forwarder\n require(\n _approvedForwarderSenders[_msgSender()].contains(sender),\n \"Sender must approve market forwarder\"\n );\n return sender;\n }\n\n return _msgSender();\n }\n\n /**\n * @notice Retrieves the actual function calldata from a trusted forwarder call.\n * @param _marketId An ID for a lending market to verify if the caller is a trusted forwarder.\n * @return calldata The modified bytes array of the function calldata without the appended sender's address.\n */\n function _msgDataForMarket(uint256 _marketId)\n internal\n view\n virtual\n returns (bytes calldata)\n {\n if (isTrustedMarketForwarder(_marketId, _msgSender())) {\n return msg.data[:msg.data.length - 20];\n } else {\n return _msgData();\n }\n }\n}\n" + }, + "contracts/TellerV2MarketForwarder_G1.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./interfaces/ITellerV2.sol\";\n\nimport \"./interfaces/IMarketRegistry.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\n\n/**\n * @dev Simple helper contract to forward an encoded function call to the TellerV2 contract. See {TellerV2Context}\n */\nabstract contract TellerV2MarketForwarder_G1 is\n Initializable,\n ContextUpgradeable\n{\n using AddressUpgradeable for address;\n\n address public immutable _tellerV2;\n address public immutable _marketRegistry;\n\n struct CreateLoanArgs {\n uint256 marketId;\n address lendingToken;\n uint256 principal;\n uint32 duration;\n uint16 interestRate;\n string metadataURI;\n address recipient;\n }\n\n constructor(address _protocolAddress, address _marketRegistryAddress) {\n _tellerV2 = _protocolAddress;\n _marketRegistry = _marketRegistryAddress;\n }\n\n function getTellerV2() public view returns (address) {\n return _tellerV2;\n }\n\n function getMarketRegistry() public view returns (address) {\n return _marketRegistry;\n }\n\n function getTellerV2MarketOwner(uint256 marketId) public returns (address) {\n return IMarketRegistry(getMarketRegistry()).getMarketOwner(marketId);\n }\n\n /**\n * @dev Performs function call to the TellerV2 contract by appending an address to the calldata.\n * @param _data The encoded function calldata on TellerV2.\n * @param _msgSender The address that should be treated as the underlying function caller.\n * @return The encoded response from the called function.\n *\n * Requirements:\n * - The {_msgSender} address must set an approval on TellerV2 for this forwarder contract __before__ making this call.\n */\n function _forwardCall(bytes memory _data, address _msgSender)\n internal\n returns (bytes memory)\n {\n return\n address(_tellerV2).functionCall(\n abi.encodePacked(_data, _msgSender)\n );\n }\n\n /**\n * @notice Creates a new loan using the TellerV2 lending protocol.\n * @param _createLoanArgs Details describing the loan agreement.]\n * @param _borrower The borrower address for the new loan.\n */\n function _submitBid(\n CreateLoanArgs memory _createLoanArgs,\n address _borrower\n ) internal virtual returns (uint256 bidId) {\n bytes memory responseData;\n\n responseData = _forwardCall(\n abi.encodeWithSignature(\n \"submitBid(address,uint256,uint256,uint32,uint16,string,address)\",\n _createLoanArgs.lendingToken,\n _createLoanArgs.marketId,\n _createLoanArgs.principal,\n _createLoanArgs.duration,\n _createLoanArgs.interestRate,\n _createLoanArgs.metadataURI,\n _createLoanArgs.recipient\n ),\n _borrower\n );\n\n return abi.decode(responseData, (uint256));\n }\n\n /**\n * @notice Creates a new loan using the TellerV2 lending protocol.\n * @param _createLoanArgs Details describing the loan agreement.]\n * @param _borrower The borrower address for the new loan.\n */\n function _submitBidWithCollateral(\n CreateLoanArgs memory _createLoanArgs,\n Collateral[] memory _collateralInfo,\n address _borrower\n ) internal virtual returns (uint256 bidId) {\n bytes memory responseData;\n\n responseData = _forwardCall(\n abi.encodeWithSignature(\n \"submitBid(address,uint256,uint256,uint32,uint16,string,address,(uint8,uint256,uint256,address)[])\",\n _createLoanArgs.lendingToken,\n _createLoanArgs.marketId,\n _createLoanArgs.principal,\n _createLoanArgs.duration,\n _createLoanArgs.interestRate,\n _createLoanArgs.metadataURI,\n _createLoanArgs.recipient,\n _collateralInfo\n ),\n _borrower\n );\n\n return abi.decode(responseData, (uint256));\n }\n\n /**\n * @notice Accepts a new loan using the TellerV2 lending protocol.\n * @param _bidId The id of the new loan.\n * @param _lender The address of the lender who will provide funds for the new loan.\n */\n function _acceptBid(uint256 _bidId, address _lender)\n internal\n virtual\n returns (bool)\n {\n // Approve the borrower's loan\n _forwardCall(\n abi.encodeWithSelector(ITellerV2.lenderAcceptBid.selector, _bidId),\n _lender\n );\n\n return true;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/TellerV2MarketForwarder_G2.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./interfaces/ITellerV2.sol\";\n\nimport \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/ITellerV2MarketForwarder.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\n\n/**\n * @dev Simple helper contract to forward an encoded function call to the TellerV2 contract. See {TellerV2Context}\n */\nabstract contract TellerV2MarketForwarder_G2 is\n Initializable,\n ContextUpgradeable,\n ITellerV2MarketForwarder\n{\n using AddressUpgradeable for address;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable _tellerV2;\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable _marketRegistry;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _protocolAddress, address _marketRegistryAddress) {\n _tellerV2 = _protocolAddress;\n _marketRegistry = _marketRegistryAddress;\n }\n\n function getTellerV2() public view returns (address) {\n return _tellerV2;\n }\n\n function getMarketRegistry() public view returns (address) {\n return _marketRegistry;\n }\n\n function getTellerV2MarketOwner(uint256 marketId) public returns (address) {\n return IMarketRegistry(getMarketRegistry()).getMarketOwner(marketId);\n }\n\n /**\n * @dev Performs function call to the TellerV2 contract by appending an address to the calldata.\n * @param _data The encoded function calldata on TellerV2.\n * @param _msgSender The address that should be treated as the underlying function caller.\n * @return The encoded response from the called function.\n *\n * Requirements:\n * - The {_msgSender} address must set an approval on TellerV2 for this forwarder contract __before__ making this call.\n */\n function _forwardCall(bytes memory _data, address _msgSender)\n internal\n returns (bytes memory)\n {\n return\n address(_tellerV2).functionCall(\n abi.encodePacked(_data, _msgSender)\n );\n }\n\n /**\n * @notice Creates a new loan using the TellerV2 lending protocol.\n * @param _createLoanArgs Details describing the loan agreement.]\n * @param _borrower The borrower address for the new loan.\n */\n /*function _submitBid(\n CreateLoanArgs memory _createLoanArgs,\n address _borrower\n ) internal virtual returns (uint256 bidId) {\n bytes memory responseData;\n\n responseData = _forwardCall(\n abi.encodeWithSignature(\n \"submitBid(address,uint256,uint256,uint32,uint16,string,address)\",\n _createLoanArgs.lendingToken,\n _createLoanArgs.marketId,\n _createLoanArgs.principal,\n _createLoanArgs.duration,\n _createLoanArgs.interestRate,\n _createLoanArgs.metadataURI,\n _createLoanArgs.recipient\n ),\n _borrower\n );\n\n return abi.decode(responseData, (uint256));\n }*/\n\n /**\n * @notice Creates a new loan using the TellerV2 lending protocol.\n * @param _createLoanArgs Details describing the loan agreement.]\n * @param _borrower The borrower address for the new loan.\n */\n function _submitBidWithCollateral(\n CreateLoanArgs memory _createLoanArgs,\n address _borrower\n ) internal virtual returns (uint256 bidId) {\n bytes memory responseData;\n\n responseData = _forwardCall(\n abi.encodeWithSignature(\n \"submitBid(address,uint256,uint256,uint32,uint16,string,address,(uint8,uint256,uint256,address)[])\",\n _createLoanArgs.lendingToken,\n _createLoanArgs.marketId,\n _createLoanArgs.principal,\n _createLoanArgs.duration,\n _createLoanArgs.interestRate,\n _createLoanArgs.metadataURI,\n _createLoanArgs.recipient,\n _createLoanArgs.collateral\n ),\n _borrower\n );\n\n return abi.decode(responseData, (uint256));\n }\n\n /**\n * @notice Accepts a new loan using the TellerV2 lending protocol.\n * @param _bidId The id of the new loan.\n * @param _lender The address of the lender who will provide funds for the new loan.\n */\n function _acceptBid(uint256 _bidId, address _lender)\n internal\n virtual\n returns (bool)\n {\n // Approve the borrower's loan\n _forwardCall(\n abi.encodeWithSelector(ITellerV2.lenderAcceptBid.selector, _bidId),\n _lender\n );\n\n return true;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "contracts/TellerV2MarketForwarder_G3.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport \"./interfaces/ITellerV2.sol\";\n\nimport \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/ITellerV2MarketForwarder.sol\";\nimport \"./interfaces/ILoanRepaymentCallbacks.sol\";\n\nimport \"./TellerV2MarketForwarder_G2.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\";\n\n/**\n * @dev Simple helper contract to forward an encoded function call to the TellerV2 contract. See {TellerV2Context}\n */\nabstract contract TellerV2MarketForwarder_G3 is TellerV2MarketForwarder_G2 {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _protocolAddress, address _marketRegistryAddress)\n TellerV2MarketForwarder_G2(_protocolAddress, _marketRegistryAddress)\n {}\n\n /**\n * @notice Accepts a new loan using the TellerV2 lending protocol.\n * @param _bidId The id of the new loan.\n * @param _lender The address of the lender who will provide funds for the new loan.\n */\n function _acceptBidWithRepaymentListener(\n uint256 _bidId,\n address _lender,\n address _listener\n ) internal virtual returns (bool) {\n // Approve the borrower's loan\n _forwardCall(\n abi.encodeWithSelector(ITellerV2.lenderAcceptBid.selector, _bidId),\n _lender\n );\n\n _forwardCall(\n abi.encodeWithSelector(\n ILoanRepaymentCallbacks.setRepaymentListenerForBid.selector,\n _bidId,\n _listener\n ),\n _lender\n );\n\n //ITellerV2(getTellerV2()).setRepaymentListenerForBid(_bidId, _listener);\n\n return true;\n }\n\n //a gap is inherited from g2 so this is actually not necessary going forwards ---leaving it to maintain upgradeability\n uint256[50] private __gap;\n}\n" + }, + "contracts/TellerV2Storage.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\nimport { IMarketRegistry } from \"./interfaces/IMarketRegistry.sol\";\nimport \"./interfaces/IEscrowVault.sol\";\nimport \"./interfaces/IReputationManager.sol\";\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./interfaces/ICollateralManager.sol\";\nimport { PaymentType, PaymentCycleType } from \"./libraries/V2Calculations.sol\";\nimport \"./interfaces/ILenderManager.sol\";\n\nenum BidState {\n NONEXISTENT,\n PENDING,\n CANCELLED,\n ACCEPTED,\n PAID,\n LIQUIDATED,\n CLOSED\n}\n\n/**\n * @notice Represents a total amount for a payment.\n * @param principal Amount that counts towards the principal.\n * @param interest Amount that counts toward interest.\n */\nstruct Payment {\n uint256 principal;\n uint256 interest;\n}\n\n/**\n * @notice Details about a loan request.\n * @param borrower Account address who is requesting a loan.\n * @param receiver Account address who will receive the loan amount.\n * @param lender Account address who accepted and funded the loan request.\n * @param marketplaceId ID of the marketplace the bid was submitted to.\n * @param metadataURI ID of off chain metadata to find additional information of the loan request.\n * @param loanDetails Struct of the specific loan details.\n * @param terms Struct of the loan request terms.\n * @param state Represents the current state of the loan.\n */\nstruct Bid {\n address borrower;\n address receiver;\n address lender; // if this is the LenderManager address, we use that .owner() as source of truth\n uint256 marketplaceId;\n bytes32 _metadataURI; // DEPRECATED\n LoanDetails loanDetails;\n Terms terms;\n BidState state;\n PaymentType paymentType;\n}\n\n/**\n * @notice Details about the loan.\n * @param lendingToken The token address for the loan.\n * @param principal The amount of tokens initially lent out.\n * @param totalRepaid Payment struct that represents the total principal and interest amount repaid.\n * @param timestamp Timestamp, in seconds, of when the bid was submitted by the borrower.\n * @param acceptedTimestamp Timestamp, in seconds, of when the bid was accepted by the lender.\n * @param lastRepaidTimestamp Timestamp, in seconds, of when the last payment was made\n * @param loanDuration The duration of the loan.\n */\nstruct LoanDetails {\n IERC20 lendingToken;\n uint256 principal;\n Payment totalRepaid;\n uint32 timestamp;\n uint32 acceptedTimestamp;\n uint32 lastRepaidTimestamp;\n uint32 loanDuration;\n}\n\n/**\n * @notice Information on the terms of a loan request\n * @param paymentCycleAmount Value of tokens expected to be repaid every payment cycle.\n * @param paymentCycle Duration, in seconds, of how often a payment must be made.\n * @param APR Annual percentage rating to be applied on repayments. (10000 == 100%)\n */\nstruct Terms {\n uint256 paymentCycleAmount;\n uint32 paymentCycle;\n uint16 APR;\n}\n\nabstract contract TellerV2Storage_G0 {\n /** Storage Variables */\n\n // Current number of bids.\n uint256 public bidId;\n\n // Mapping of bidId to bid information.\n mapping(uint256 => Bid) public bids;\n\n // Mapping of borrowers to borrower requests.\n mapping(address => uint256[]) public borrowerBids;\n\n // Mapping of volume filled by lenders.\n mapping(address => uint256) public __lenderVolumeFilled; // DEPRECIATED\n\n // Volume filled by all lenders.\n uint256 public __totalVolumeFilled; // DEPRECIATED\n\n // List of allowed lending tokens\n EnumerableSet.AddressSet internal __lendingTokensSet; // DEPRECATED\n\n IMarketRegistry public marketRegistry;\n IReputationManager public reputationManager;\n\n // Mapping of borrowers to borrower requests.\n mapping(address => EnumerableSet.UintSet) internal _borrowerBidsActive;\n\n mapping(uint256 => uint32) public bidDefaultDuration;\n mapping(uint256 => uint32) public bidExpirationTime;\n\n // Mapping of volume filled by lenders.\n // Asset address => Lender address => Volume amount\n mapping(address => mapping(address => uint256)) public lenderVolumeFilled;\n\n // Volume filled by all lenders.\n // Asset address => Volume amount\n mapping(address => uint256) public totalVolumeFilled;\n\n uint256 public version;\n\n // Mapping of metadataURIs by bidIds.\n // Bid Id => metadataURI string\n mapping(uint256 => string) public uris;\n}\n\nabstract contract TellerV2Storage_G1 is TellerV2Storage_G0 {\n // market ID => trusted forwarder\n mapping(uint256 => address) internal _trustedMarketForwarders;\n // trusted forwarder => set of pre-approved senders\n mapping(address => EnumerableSet.AddressSet)\n internal _approvedForwarderSenders;\n}\n\nabstract contract TellerV2Storage_G2 is TellerV2Storage_G1 {\n address public lenderCommitmentForwarder;\n}\n\nabstract contract TellerV2Storage_G3 is TellerV2Storage_G2 {\n ICollateralManager public collateralManager;\n}\n\nabstract contract TellerV2Storage_G4 is TellerV2Storage_G3 {\n // Address of the lender manager contract\n ILenderManager public lenderManager;\n // BidId to payment cycle type (custom or monthly)\n mapping(uint256 => PaymentCycleType) public bidPaymentCycleType;\n}\n\nabstract contract TellerV2Storage_G5 is TellerV2Storage_G4 {\n // Address of the lender manager contract\n IEscrowVault public escrowVault;\n}\n\nabstract contract TellerV2Storage_G6 is TellerV2Storage_G5 {\n mapping(uint256 => address) public repaymentListenerForBid;\n}\n\nabstract contract TellerV2Storage_G7 is TellerV2Storage_G6 {\n mapping(address => bool) private __pauserRoleBearer ;//pauserRoleBearer;\n bool private __liquidationsPaused; //liquidations paused\n}\n\nabstract contract TellerV2Storage is TellerV2Storage_G7 {}\n" + }, + "contracts/Types.sol": { + "content": "pragma solidity >=0.8.0 <0.9.0;\n// SPDX-License-Identifier: MIT\n\n// A representation of an empty/uninitialized UUID.\nbytes32 constant EMPTY_UUID = 0;\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file From 433689f2df2778df7c5d2d23909edcf6dcb76bb0 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Mon, 14 Oct 2024 17:53:37 -0400 Subject: [PATCH 24/32] proposed upgrades --- packages/contracts/.openzeppelin/polygon.json | 1364 ++++++++++++++++- .../18_upgrade_teller_v2_pause_manager.ts | 2 +- .../deployments/polygon/.migrations.json | 4 +- .../polygon/CollateralManager.json | 742 +++++---- .../polygon/LenderCommitmentGroupBeacon.json | 34 +- .../polygon/SmartCommitmentForwarder.json | 16 +- .../deployments/polygon/TellerV2.json | 181 +-- 7 files changed, 1806 insertions(+), 537 deletions(-) diff --git a/packages/contracts/.openzeppelin/polygon.json b/packages/contracts/.openzeppelin/polygon.json index 3ab95b4cf..a2c253f32 100644 --- a/packages/contracts/.openzeppelin/polygon.json +++ b/packages/contracts/.openzeppelin/polygon.json @@ -3096,8 +3096,8 @@ } }, "797b64d3b87c3178c44d57ca0bba037d86cf9710f40eb2d971cc017ba18a17ec": { - "address": "0x5Bb23271A93433B13c13D19826bc155a00694B2E", - "txHash": "0x5896063ec3cd5fcbe35c0673d7a6f9d0ba2a5f1fc0c89bff6cef6206e5cab2e8", + "address": "0x48f4DDbc34A0DF3b5aC2B13Db4895fa980607aa9", + "txHash": "0xbcc2ff9364ae40b920ce74a25c4cf56f666527214696286acb373f93f212953a", "layout": { "solcVersion": "0.8.9", "storage": [ @@ -10327,6 +10327,1366 @@ }, "namespaces": {} } + }, + "4e482cd28849c2936bc69df1ccbc53afd300d2cc6f65838a7d3b46deef862d55": { + "address": "0xe8E5BECFAC5029464243509a236217B3cC682459", + "txHash": "0x9e994e23bf8cd191961be39faf247c2c916c8a4cd4e1b395283ba4e2ed1b7184", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_protocolFee", + "offset": 0, + "slot": "101", + "type": "t_uint16", + "contract": "ProtocolFee", + "src": "contracts/ProtocolFee.sol:8" + }, + { + "label": "__paused", + "offset": 2, + "slot": "101", + "type": "t_bool", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:22" + }, + { + "label": "_protocolPausingManager", + "offset": 3, + "slot": "101", + "type": "t_address", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)48_storage", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:61" + }, + { + "label": "bidId", + "offset": 0, + "slot": "150", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:92" + }, + { + "label": "bids", + "offset": 0, + "slot": "151", + "type": "t_mapping(t_uint256,t_struct(Bid)9763_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:95" + }, + { + "label": "borrowerBids", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:98" + }, + { + "label": "__lenderVolumeFilled", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:101" + }, + { + "label": "__totalVolumeFilled", + "offset": 0, + "slot": "154", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:104" + }, + { + "label": "__lendingTokensSet", + "offset": 0, + "slot": "155", + "type": "t_struct(AddressSet)5563_storage", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:107" + }, + { + "label": "marketRegistry", + "offset": 0, + "slot": "157", + "type": "t_contract(IMarketRegistry)10636", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:109" + }, + { + "label": "reputationManager", + "offset": 0, + "slot": "158", + "type": "t_contract(IReputationManager)10723", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:110" + }, + { + "label": "_borrowerBidsActive", + "offset": 0, + "slot": "159", + "type": "t_mapping(t_address,t_struct(UintSet)5720_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:113" + }, + { + "label": "bidDefaultDuration", + "offset": 0, + "slot": "160", + "type": "t_mapping(t_uint256,t_uint32)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:115" + }, + { + "label": "bidExpirationTime", + "offset": 0, + "slot": "161", + "type": "t_mapping(t_uint256,t_uint32)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:116" + }, + { + "label": "lenderVolumeFilled", + "offset": 0, + "slot": "162", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:120" + }, + { + "label": "totalVolumeFilled", + "offset": 0, + "slot": "163", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:124" + }, + { + "label": "version", + "offset": 0, + "slot": "164", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:126" + }, + { + "label": "uris", + "offset": 0, + "slot": "165", + "type": "t_mapping(t_uint256,t_string_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:130" + }, + { + "label": "_trustedMarketForwarders", + "offset": 0, + "slot": "166", + "type": "t_mapping(t_uint256,t_address)", + "contract": "TellerV2Storage_G1", + "src": "contracts/TellerV2Storage.sol:135" + }, + { + "label": "_approvedForwarderSenders", + "offset": 0, + "slot": "167", + "type": "t_mapping(t_address,t_struct(AddressSet)5563_storage)", + "contract": "TellerV2Storage_G1", + "src": "contracts/TellerV2Storage.sol:137" + }, + { + "label": "lenderCommitmentForwarder", + "offset": 0, + "slot": "168", + "type": "t_address", + "contract": "TellerV2Storage_G2", + "src": "contracts/TellerV2Storage.sol:142" + }, + { + "label": "collateralManager", + "offset": 0, + "slot": "169", + "type": "t_contract(ICollateralManager)10101", + "contract": "TellerV2Storage_G3", + "src": "contracts/TellerV2Storage.sol:146" + }, + { + "label": "lenderManager", + "offset": 0, + "slot": "170", + "type": "t_contract(ILenderManager)10443", + "contract": "TellerV2Storage_G4", + "src": "contracts/TellerV2Storage.sol:151" + }, + { + "label": "bidPaymentCycleType", + "offset": 0, + "slot": "171", + "type": "t_mapping(t_uint256,t_enum(PaymentCycleType)12767)", + "contract": "TellerV2Storage_G4", + "src": "contracts/TellerV2Storage.sol:153" + }, + { + "label": "escrowVault", + "offset": 0, + "slot": "172", + "type": "t_contract(IEscrowVault)10421", + "contract": "TellerV2Storage_G5", + "src": "contracts/TellerV2Storage.sol:158" + }, + { + "label": "repaymentListenerForBid", + "offset": 0, + "slot": "173", + "type": "t_mapping(t_uint256,t_address)", + "contract": "TellerV2Storage_G6", + "src": "contracts/TellerV2Storage.sol:162" + }, + { + "label": "__pauserRoleBearer", + "offset": 0, + "slot": "174", + "type": "t_mapping(t_address,t_bool)", + "contract": "TellerV2Storage_G7", + "src": "contracts/TellerV2Storage.sol:166" + }, + { + "label": "__liquidationsPaused", + "offset": 0, + "slot": "175", + "type": "t_bool", + "contract": "TellerV2Storage_G7", + "src": "contracts/TellerV2Storage.sol:167" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_array(t_uint256)dyn_storage": { + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ICollateralManager)10101": { + "label": "contract ICollateralManager", + "numberOfBytes": "20" + }, + "t_contract(IERC20)1872": { + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IEscrowVault)10421": { + "label": "contract IEscrowVault", + "numberOfBytes": "20" + }, + "t_contract(ILenderManager)10443": { + "label": "contract ILenderManager", + "numberOfBytes": "20" + }, + "t_contract(IMarketRegistry)10636": { + "label": "contract IMarketRegistry", + "numberOfBytes": "20" + }, + "t_contract(IReputationManager)10723": { + "label": "contract IReputationManager", + "numberOfBytes": "20" + }, + "t_enum(BidState)9735": { + "label": "enum BidState", + "members": [ + "NONEXISTENT", + "PENDING", + "CANCELLED", + "ACCEPTED", + "PAID", + "LIQUIDATED", + "CLOSED" + ], + "numberOfBytes": "1" + }, + "t_enum(PaymentCycleType)12767": { + "label": "enum PaymentCycleType", + "members": [ + "Seconds", + "Monthly" + ], + "numberOfBytes": "1" + }, + "t_enum(PaymentType)12764": { + "label": "enum PaymentType", + "members": [ + "EMI", + "Bullet" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { + "label": "mapping(address => uint256[])", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(AddressSet)5563_storage)": { + "label": "mapping(address => struct EnumerableSet.AddressSet)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(UintSet)5720_storage)": { + "label": "mapping(address => struct EnumerableSet.UintSet)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_enum(PaymentCycleType)12767)": { + "label": "mapping(uint256 => enum PaymentCycleType)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_string_storage)": { + "label": "mapping(uint256 => string)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Bid)9763_storage)": { + "label": "mapping(uint256 => struct Bid)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint32)": { + "label": "mapping(uint256 => uint32)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)5563_storage": { + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)5248_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Bid)9763_storage": { + "label": "struct Bid", + "members": [ + { + "label": "borrower", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "receiver", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "lender", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "marketplaceId", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "_metadataURI", + "type": "t_bytes32", + "offset": 0, + "slot": "4" + }, + { + "label": "loanDetails", + "type": "t_struct(LoanDetails)9780_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "terms", + "type": "t_struct(Terms)9787_storage", + "offset": 0, + "slot": "10" + }, + { + "label": "state", + "type": "t_enum(BidState)9735", + "offset": 0, + "slot": "12" + }, + { + "label": "paymentType", + "type": "t_enum(PaymentType)12764", + "offset": 1, + "slot": "12" + } + ], + "numberOfBytes": "416" + }, + "t_struct(LoanDetails)9780_storage": { + "label": "struct LoanDetails", + "members": [ + { + "label": "lendingToken", + "type": "t_contract(IERC20)1872", + "offset": 0, + "slot": "0" + }, + { + "label": "principal", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "totalRepaid", + "type": "t_struct(Payment)9740_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "timestamp", + "type": "t_uint32", + "offset": 0, + "slot": "4" + }, + { + "label": "acceptedTimestamp", + "type": "t_uint32", + "offset": 4, + "slot": "4" + }, + { + "label": "lastRepaidTimestamp", + "type": "t_uint32", + "offset": 8, + "slot": "4" + }, + { + "label": "loanDuration", + "type": "t_uint32", + "offset": 12, + "slot": "4" + } + ], + "numberOfBytes": "160" + }, + "t_struct(Payment)9740_storage": { + "label": "struct Payment", + "members": [ + { + "label": "principal", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "interest", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)5248_storage": { + "label": "struct EnumerableSet.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Terms)9787_storage": { + "label": "struct Terms", + "members": [ + { + "label": "paymentCycleAmount", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "paymentCycle", + "type": "t_uint32", + "offset": 0, + "slot": "1" + }, + { + "label": "APR", + "type": "t_uint16", + "offset": 4, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(UintSet)5720_storage": { + "label": "struct EnumerableSet.UintSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)5248_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "3e22bc6145241e2f794964b3409c0fc9639f6c3471ff2a8bad272b27d9a8b315": { + "address": "0xF27E3Be6382281644405fc4218F83D07f36f3142", + "txHash": "0xdbeb67f164af0f433ae32833292f4f1a4ada5bd5cd841544330f3f134dd8b91a", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "tellerV2", + "offset": 0, + "slot": "101", + "type": "t_contract(ITellerV2)32026", + "contract": "CollateralManager", + "src": "contracts/CollateralManager.sol:24" + }, + { + "label": "collateralEscrowBeacon", + "offset": 0, + "slot": "102", + "type": "t_address", + "contract": "CollateralManager", + "src": "contracts/CollateralManager.sol:25" + }, + { + "label": "_escrows", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_uint256,t_address)", + "contract": "CollateralManager", + "src": "contracts/CollateralManager.sol:28" + }, + { + "label": "_bidCollaterals", + "offset": 0, + "slot": "104", + "type": "t_mapping(t_uint256,t_struct(CollateralInfo)9944_storage)", + "contract": "CollateralManager", + "src": "contracts/CollateralManager.sol:30" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ITellerV2)32026": { + "label": "contract ITellerV2", + "numberOfBytes": "20" + }, + "t_enum(CollateralType)33375": { + "label": "enum CollateralType", + "members": [ + "ERC20", + "ERC721", + "ERC1155" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_struct(Collateral)33385_storage)": { + "label": "mapping(address => struct Collateral)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(CollateralInfo)9944_storage)": { + "label": "mapping(uint256 => struct CollateralManager.CollateralInfo)", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)4120_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)3805_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Collateral)33385_storage": { + "label": "struct Collateral", + "members": [ + { + "label": "_collateralType", + "type": "t_enum(CollateralType)33375", + "offset": 0, + "slot": "0" + }, + { + "label": "_amount", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "_tokenId", + "type": "t_uint256", + "offset": 0, + "slot": "2" + }, + { + "label": "_collateralAddress", + "type": "t_address", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(CollateralInfo)9944_storage": { + "label": "struct CollateralManager.CollateralInfo", + "members": [ + { + "label": "collateralAddresses", + "type": "t_struct(AddressSet)4120_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "collateralInfo", + "type": "t_mapping(t_address,t_struct(Collateral)33385_storage)", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(Set)3805_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "86cb4abd97cd22a4544e8991d50663bf83b66df2478b8f707c9a2909aedcbbd4": { + "address": "0xF579ba9Ce33E392134Fd4a1A9D7D9d792eAF0B2b", + "txHash": "0x90da625975542f23ad05712e85cab34e7dd869d0eeb32bf9684dfcb8f437b1c3", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "userExtensions", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ExtensionsContextUpgradeable", + "src": "contracts/LenderCommitmentForwarder/extensions/ExtensionsContextUpgradeable.sol:12" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)49_storage", + "contract": "ExtensionsContextUpgradeable", + "src": "contracts/LenderCommitmentForwarder/extensions/ExtensionsContextUpgradeable.sol:61" + }, + { + "label": "_initialized", + "offset": 0, + "slot": "50", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "50", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)50_storage", + "contract": "TellerV2MarketForwarder_G2", + "src": "contracts/TellerV2MarketForwarder_G2.sol:149" + }, + { + "label": "__gap", + "offset": 0, + "slot": "151", + "type": "t_array(t_uint256)50_storage", + "contract": "TellerV2MarketForwarder_G3", + "src": "contracts/TellerV2MarketForwarder_G3.sol:59" + }, + { + "label": "_paused", + "offset": 0, + "slot": "201", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "202", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "liquidationProtocolFeePercent", + "offset": 0, + "slot": "251", + "type": "t_uint256", + "contract": "SmartCommitmentForwarder", + "src": "contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol:59" + }, + { + "label": "lastUnpausedAt", + "offset": 0, + "slot": "252", + "type": "t_uint256", + "contract": "SmartCommitmentForwarder", + "src": "contracts/LenderCommitmentForwarder/SmartCommitmentForwarder.sol:60" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "a2339f19ef158da60344cf5031eaf3ea132ec6866506990f8373a38460d9e8c4": { + "address": "0xfdC723Aa9874530470DA36cc0791b7DC1201a6ec", + "txHash": "0x71b5d480ded8808185d775ef700a15d082172749ee7b5a6a9d1d66c40f079ebb", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "UNISWAP_V3_POOL", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:97" + }, + { + "label": "poolSharesToken", + "offset": 0, + "slot": "152", + "type": "t_contract(LenderCommitmentGroupShares)21254", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:99" + }, + { + "label": "principalToken", + "offset": 0, + "slot": "153", + "type": "t_contract(IERC20)5810", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:101" + }, + { + "label": "collateralToken", + "offset": 0, + "slot": "154", + "type": "t_contract(IERC20)5810", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:102" + }, + { + "label": "_uniswapPoolFee", + "offset": 20, + "slot": "154", + "type": "t_uint24", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:103" + }, + { + "label": "marketId", + "offset": 0, + "slot": "155", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:105" + }, + { + "label": "totalPrincipalTokensCommitted", + "offset": 0, + "slot": "156", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:108" + }, + { + "label": "totalPrincipalTokensWithdrawn", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:109" + }, + { + "label": "totalPrincipalTokensLended", + "offset": 0, + "slot": "158", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:111" + }, + { + "label": "totalPrincipalTokensRepaid", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:112" + }, + { + "label": "totalInterestCollected", + "offset": 0, + "slot": "160", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:116" + }, + { + "label": "liquidityThresholdPercent", + "offset": 0, + "slot": "161", + "type": "t_uint16", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:118" + }, + { + "label": "collateralRatio", + "offset": 2, + "slot": "161", + "type": "t_uint16", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:119" + }, + { + "label": "_twapInterval", + "offset": 4, + "slot": "161", + "type": "t_uint32", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:121" + }, + { + "label": "maxLoanDuration", + "offset": 8, + "slot": "161", + "type": "t_uint32", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:122" + }, + { + "label": "interestRateLowerBound", + "offset": 12, + "slot": "161", + "type": "t_uint16", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:123" + }, + { + "label": "interestRateUpperBound", + "offset": 14, + "slot": "161", + "type": "t_uint16", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:124" + }, + { + "label": "poolSharesPreparedToWithdrawForLender", + "offset": 0, + "slot": "162", + "type": "t_mapping(t_address,t_uint256)", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:129" + }, + { + "label": "poolSharesPreparedTimestamp", + "offset": 0, + "slot": "163", + "type": "t_mapping(t_address,t_uint256)", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:130" + }, + { + "label": "activeBids", + "offset": 0, + "slot": "164", + "type": "t_mapping(t_uint256,t_bool)", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:135" + }, + { + "label": "tokenDifferenceFromLiquidations", + "offset": 0, + "slot": "165", + "type": "t_int256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:139" + }, + { + "label": "firstDepositMade", + "offset": 0, + "slot": "166", + "type": "t_bool", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:141" + }, + { + "label": "withdrawlDelayTimeSeconds", + "offset": 0, + "slot": "167", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:142" + }, + { + "label": "poolOracleRoutes", + "offset": 0, + "slot": "168", + "type": "t_array(t_struct(PoolRouteConfig)32115_storage)dyn_storage", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:144" + }, + { + "label": "maxPrincipalPerCollateralAmount", + "offset": 0, + "slot": "169", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:147" + }, + { + "label": "lastUnpausedAt", + "offset": 0, + "slot": "170", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:150" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(PoolRouteConfig)32115_storage)dyn_storage": { + "label": "struct IUniswapPricingLibrary.PoolRouteConfig[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)5810": { + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(LenderCommitmentGroupShares)21254": { + "label": "contract LenderCommitmentGroupShares", + "numberOfBytes": "20" + }, + "t_int256": { + "label": "int256", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_struct(PoolRouteConfig)32115_storage": { + "label": "struct IUniswapPricingLibrary.PoolRouteConfig", + "members": [ + { + "label": "pool", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "zeroForOne", + "type": "t_bool", + "offset": 20, + "slot": "0" + }, + { + "label": "twapInterval", + "type": "t_uint32", + "offset": 21, + "slot": "0" + }, + { + "label": "token0Decimals", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "token1Decimals", + "type": "t_uint256", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint24": { + "label": "uint24", + "numberOfBytes": "3" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts index 006c866e0..0b2e32ed7 100644 --- a/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts +++ b/packages/contracts/deploy/upgrades/18_upgrade_teller_v2_pause_manager.ts @@ -41,7 +41,7 @@ const deployFn: DeployFunction = async (hre) => { }), opts: { - // unsafeSkipStorageCheck: true, + unsafeSkipStorageCheck: true, // ! unsafeAllow: [ 'constructor', 'state-variable-immutable', diff --git a/packages/contracts/deployments/polygon/.migrations.json b/packages/contracts/deployments/polygon/.migrations.json index dd04aa678..4d6b7b269 100644 --- a/packages/contracts/deployments/polygon/.migrations.json +++ b/packages/contracts/deployments/polygon/.migrations.json @@ -35,5 +35,7 @@ "teller-v2:pausing-upgrade": 1727280937, "lender-commitment-group-factory:upgrade-multihop": 1727465789, "smart-commitment-forwarder:upgrade-pausing": 1727811173, - "protocol-pausing-manager:deploy": 1728941512 + "protocol-pausing-manager:deploy": 1728941512, + "teller-v2:pausing-manager-upgrade": 1728942782, + "lender-commitment-group-beacon:upgrade": 1728942801 } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/CollateralManager.json b/packages/contracts/deployments/polygon/CollateralManager.json index 497164d78..e3f904cb9 100644 --- a/packages/contracts/deployments/polygon/CollateralManager.json +++ b/packages/contracts/deployments/polygon/CollateralManager.json @@ -2,715 +2,697 @@ "address": "0x76888a882a4fF57455B5e74B791DD19DF3ba51Bb", "abi": [ { + "type": "event", "anonymous": false, + "name": "CollateralClaimed", "inputs": [ { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_bidId", - "type": "uint256" + "indexed": false } - ], - "name": "CollateralClaimed", - "type": "event" + ] }, { + "type": "event", "anonymous": false, + "name": "CollateralCommitted", "inputs": [ { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_bidId", - "type": "uint256" + "indexed": false }, { - "indexed": false, - "internalType": "enum CollateralType", + "type": "uint8", "name": "_type", - "type": "uint8" + "indexed": false }, { - "indexed": false, - "internalType": "address", + "type": "address", "name": "_collateralAddress", - "type": "address" + "indexed": false }, { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_amount", - "type": "uint256" + "indexed": false }, { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_tokenId", - "type": "uint256" + "indexed": false } - ], - "name": "CollateralCommitted", - "type": "event" + ] }, { + "type": "event", "anonymous": false, + "name": "CollateralDeposited", "inputs": [ { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_bidId", - "type": "uint256" + "indexed": false }, { - "indexed": false, - "internalType": "enum CollateralType", + "type": "uint8", "name": "_type", - "type": "uint8" + "indexed": false }, { - "indexed": false, - "internalType": "address", + "type": "address", "name": "_collateralAddress", - "type": "address" + "indexed": false }, { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_amount", - "type": "uint256" + "indexed": false }, { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_tokenId", - "type": "uint256" + "indexed": false } - ], - "name": "CollateralDeposited", - "type": "event" + ] }, { + "type": "event", "anonymous": false, + "name": "CollateralEscrowDeployed", "inputs": [ { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_bidId", - "type": "uint256" + "indexed": false }, { - "indexed": false, - "internalType": "address", + "type": "address", "name": "_collateralEscrow", - "type": "address" + "indexed": false } - ], - "name": "CollateralEscrowDeployed", - "type": "event" + ] }, { + "type": "event", "anonymous": false, + "name": "CollateralWithdrawn", "inputs": [ { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_bidId", - "type": "uint256" + "indexed": false }, { - "indexed": false, - "internalType": "enum CollateralType", + "type": "uint8", "name": "_type", - "type": "uint8" + "indexed": false }, { - "indexed": false, - "internalType": "address", + "type": "address", "name": "_collateralAddress", - "type": "address" + "indexed": false }, { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_amount", - "type": "uint256" + "indexed": false }, { - "indexed": false, - "internalType": "uint256", + "type": "uint256", "name": "_tokenId", - "type": "uint256" + "indexed": false }, { - "indexed": false, - "internalType": "address", + "type": "address", "name": "_recipient", - "type": "address" + "indexed": false } - ], - "name": "CollateralWithdrawn", - "type": "event" + ] }, { + "type": "event", "anonymous": false, + "name": "Initialized", "inputs": [ { - "indexed": false, - "internalType": "uint8", + "type": "uint8", "name": "version", - "type": "uint8" + "indexed": false } - ], - "name": "Initialized", - "type": "event" + ] }, { + "type": "event", "anonymous": false, + "name": "OwnershipTransferred", "inputs": [ { - "indexed": true, - "internalType": "address", + "type": "address", "name": "previousOwner", - "type": "address" + "indexed": true }, { - "indexed": true, - "internalType": "address", + "type": "address", "name": "newOwner", - "type": "address" + "indexed": true } - ], - "name": "OwnershipTransferred", - "type": "event" + ] }, { + "type": "function", + "name": "_escrows", + "constant": true, + "stateMutability": "view", + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "type": "uint256", + "name": "" } ], - "name": "_escrows", "outputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" } - ], - "stateMutability": "view", - "type": "function" + ] }, { + "type": "function", + "name": "checkBalances", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "address", - "name": "_borrowerAddress", - "type": "address" + "type": "address", + "name": "_borrowerAddress" }, { + "type": "tuple[]", + "name": "_collateralInfo", "components": [ { - "internalType": "enum CollateralType", - "name": "_collateralType", - "type": "uint8" + "type": "uint8", + "name": "_collateralType" }, { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" + "type": "uint256", + "name": "_amount" }, { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" + "type": "uint256", + "name": "_tokenId" }, { - "internalType": "address", - "name": "_collateralAddress", - "type": "address" + "type": "address", + "name": "_collateralAddress" } - ], - "internalType": "struct Collateral[]", - "name": "_collateralInfo", - "type": "tuple[]" + ] } ], - "name": "checkBalances", "outputs": [ { - "internalType": "bool", - "name": "validated_", - "type": "bool" + "type": "bool", + "name": "validated_" }, { - "internalType": "bool[]", - "name": "checks_", - "type": "bool[]" + "type": "bool[]", + "name": "checks_" } - ], - "stateMutability": "nonpayable", - "type": "function" + ] }, { + "type": "function", + "name": "commitCollateral", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" }, { + "type": "tuple[]", + "name": "_collateralInfo", "components": [ { - "internalType": "enum CollateralType", - "name": "_collateralType", - "type": "uint8" + "type": "uint8", + "name": "_collateralType" }, { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" + "type": "uint256", + "name": "_amount" }, { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" + "type": "uint256", + "name": "_tokenId" }, { - "internalType": "address", - "name": "_collateralAddress", - "type": "address" + "type": "address", + "name": "_collateralAddress" } - ], - "internalType": "struct Collateral[]", - "name": "_collateralInfo", - "type": "tuple[]" + ] } ], - "name": "commitCollateral", "outputs": [ { - "internalType": "bool", - "name": "validation_", - "type": "bool" + "type": "bool", + "name": "validation_" } - ], - "stateMutability": "nonpayable", - "type": "function" + ] }, { + "type": "function", + "name": "commitCollateral", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" }, { + "type": "tuple", + "name": "_collateralInfo", "components": [ { - "internalType": "enum CollateralType", - "name": "_collateralType", - "type": "uint8" + "type": "uint8", + "name": "_collateralType" }, { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" + "type": "uint256", + "name": "_amount" }, { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" + "type": "uint256", + "name": "_tokenId" }, { - "internalType": "address", - "name": "_collateralAddress", - "type": "address" + "type": "address", + "name": "_collateralAddress" } - ], - "internalType": "struct Collateral", - "name": "_collateralInfo", - "type": "tuple" + ] } ], - "name": "commitCollateral", "outputs": [ { - "internalType": "bool", - "name": "validation_", - "type": "bool" + "type": "bool", + "name": "validation_" } - ], - "stateMutability": "nonpayable", - "type": "function" + ] }, { + "type": "function", + "name": "deployAndDeposit", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" } ], - "name": "deployAndDeposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "outputs": [] }, { + "type": "function", + "name": "getCollateralAmount", + "constant": true, + "stateMutability": "view", + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" }, { - "internalType": "address", - "name": "_collateralAddress", - "type": "address" + "type": "address", + "name": "_collateralAddress" } ], - "name": "getCollateralAmount", "outputs": [ { - "internalType": "uint256", - "name": "amount_", - "type": "uint256" + "type": "uint256", + "name": "amount_" } - ], - "stateMutability": "view", - "type": "function" + ] }, { + "type": "function", + "name": "getCollateralInfo", + "constant": true, + "stateMutability": "view", + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" } ], - "name": "getCollateralInfo", "outputs": [ { + "type": "tuple[]", + "name": "infos_", "components": [ { - "internalType": "enum CollateralType", - "name": "_collateralType", - "type": "uint8" + "type": "uint8", + "name": "_collateralType" }, { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" + "type": "uint256", + "name": "_amount" }, { - "internalType": "uint256", - "name": "_tokenId", - "type": "uint256" + "type": "uint256", + "name": "_tokenId" }, { - "internalType": "address", - "name": "_collateralAddress", - "type": "address" + "type": "address", + "name": "_collateralAddress" } - ], - "internalType": "struct Collateral[]", - "name": "infos_", - "type": "tuple[]" + ] } - ], - "stateMutability": "view", - "type": "function" + ] }, { + "type": "function", + "name": "getEscrow", + "constant": true, + "stateMutability": "view", + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" } ], - "name": "getEscrow", "outputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" } - ], - "stateMutability": "view", - "type": "function" + ] }, { + "type": "function", + "name": "initialize", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "address", - "name": "_collateralEscrowBeacon", - "type": "address" + "type": "address", + "name": "_collateralEscrowBeacon" }, { - "internalType": "address", - "name": "_tellerV2", - "type": "address" + "type": "address", + "name": "_tellerV2" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "outputs": [] }, { + "type": "function", + "name": "isBidCollateralBacked", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" } ], - "name": "isBidCollateralBacked", "outputs": [ { - "internalType": "bool", - "name": "", - "type": "bool" + "type": "bool", + "name": "" } - ], - "stateMutability": "nonpayable", - "type": "function" + ] }, { + "type": "function", + "name": "lenderClaimCollateral", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" } ], - "name": "lenderClaimCollateral", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "outputs": [] }, { + "type": "function", + "name": "lenderClaimCollateralWithRecipient", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" }, { - "internalType": "address", - "name": "_liquidatorAddress", - "type": "address" + "type": "address", + "name": "_collateralRecipient" } ], + "outputs": [] + }, + { + "type": "function", "name": "liquidateCollateral", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "constant": false, + "payable": false, + "inputs": [ + { + "type": "uint256", + "name": "_bidId" + }, + { + "type": "address", + "name": "_liquidatorAddress" + } + ], + "outputs": [] }, { + "type": "function", + "name": "onERC1155BatchReceived", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" }, { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" }, { - "internalType": "uint256[]", - "name": "_ids", - "type": "uint256[]" + "type": "uint256[]", + "name": "_ids" }, { - "internalType": "uint256[]", - "name": "_values", - "type": "uint256[]" + "type": "uint256[]", + "name": "_values" }, { - "internalType": "bytes", - "name": "", - "type": "bytes" + "type": "bytes", + "name": "" } ], - "name": "onERC1155BatchReceived", "outputs": [ { - "internalType": "bytes4", - "name": "", - "type": "bytes4" + "type": "bytes4", + "name": "" } - ], - "stateMutability": "nonpayable", - "type": "function" + ] }, { + "type": "function", + "name": "onERC1155Received", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" }, { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" }, { - "internalType": "uint256", - "name": "id", - "type": "uint256" + "type": "uint256", + "name": "id" }, { - "internalType": "uint256", - "name": "value", - "type": "uint256" + "type": "uint256", + "name": "value" }, { - "internalType": "bytes", - "name": "", - "type": "bytes" + "type": "bytes", + "name": "" } ], - "name": "onERC1155Received", "outputs": [ { - "internalType": "bytes4", - "name": "", - "type": "bytes4" + "type": "bytes4", + "name": "" } - ], - "stateMutability": "nonpayable", - "type": "function" + ] }, { + "type": "function", + "name": "onERC721Received", + "constant": true, + "stateMutability": "pure", + "payable": false, "inputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" }, { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "type": "uint256", + "name": "" }, { - "internalType": "bytes", - "name": "", - "type": "bytes" + "type": "bytes", + "name": "" } ], - "name": "onERC721Received", "outputs": [ { - "internalType": "bytes4", - "name": "", - "type": "bytes4" + "type": "bytes4", + "name": "" } - ], - "stateMutability": "pure", - "type": "function" + ] }, { - "inputs": [], + "type": "function", "name": "owner", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], "outputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "type": "address", + "name": "" } - ], - "stateMutability": "view", - "type": "function" + ] }, { - "inputs": [], + "type": "function", "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "constant": false, + "payable": false, + "inputs": [], + "outputs": [] }, { + "type": "function", + "name": "revalidateCollateral", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" } ], - "name": "revalidateCollateral", "outputs": [ { - "internalType": "bool", - "name": "validation_", - "type": "bool" + "type": "bool", + "name": "validation_" } - ], - "stateMutability": "nonpayable", - "type": "function" + ] }, { + "type": "function", + "name": "setCollateralEscrowBeacon", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "address", - "name": "_collateralEscrowBeacon", - "type": "address" + "type": "address", + "name": "_collateralEscrowBeacon" } ], - "name": "setCollateralEscrowBeacon", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "outputs": [] }, { - "inputs": [], + "type": "function", "name": "tellerV2", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], "outputs": [ { - "internalType": "contract ITellerV2", - "name": "", - "type": "address" + "type": "address", + "name": "" + } + ] + }, + { + "type": "function", + "name": "transferOwnership", + "constant": false, + "payable": false, + "inputs": [ + { + "type": "address", + "name": "newOwner" } ], - "stateMutability": "view", - "type": "function" + "outputs": [] }, { + "type": "function", + "name": "withdraw", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "address", - "name": "newOwner", - "type": "address" + "type": "uint256", + "name": "_bidId" } ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "outputs": [] }, { + "type": "function", + "name": "withdrawDustTokens", + "constant": false, + "payable": false, "inputs": [ { - "internalType": "uint256", - "name": "_bidId", - "type": "uint256" + "type": "uint256", + "name": "_bidId" + }, + { + "type": "address", + "name": "_tokenAddress" + }, + { + "type": "uint256", + "name": "_amount" + }, + { + "type": "address", + "name": "_recipientAddress" } ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "outputs": [] } ], "transactionHash": "0x0f0973b7c433a3935bb45e6ffc8becbb41cc3966d908048f8207af71b731c106", @@ -796,6 +778,6 @@ "status": 1, "byzantium": true }, - "numDeployments": 8, - "implementation": "0xbDF19f0cbe53BCaC880C214411bC183d1cD8A9F8" + "numDeployments": 9, + "implementation": "0x48f4ddbc34a0df3b5ac2b13db4895fa980607aa9" } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/LenderCommitmentGroupBeacon.json b/packages/contracts/deployments/polygon/LenderCommitmentGroupBeacon.json index 0275f7ded..3e5a7f019 100644 --- a/packages/contracts/deployments/polygon/LenderCommitmentGroupBeacon.json +++ b/packages/contracts/deployments/polygon/LenderCommitmentGroupBeacon.json @@ -662,6 +662,20 @@ } ] }, + { + "type": "function", + "name": "getLastUnpausedAt", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "uint256", + "name": "" + } + ] + }, { "type": "function", "name": "getMarketId", @@ -950,6 +964,20 @@ } ] }, + { + "type": "function", + "name": "lastUnpausedAt", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "uint256", + "name": "" + } + ] + }, { "type": "function", "name": "liquidateDefaultedLoanWithIncentive", @@ -1025,7 +1053,7 @@ }, { "type": "function", - "name": "pauseBorrowing", + "name": "pauseLendingPool", "constant": false, "payable": false, "inputs": [], @@ -1336,7 +1364,7 @@ }, { "type": "function", - "name": "unpauseBorrowing", + "name": "unpauseLendingPool", "constant": false, "payable": false, "inputs": [], @@ -1371,6 +1399,6 @@ } ], "receipt": {}, - "numDeployments": 7, + "numDeployments": 8, "implementation": "0x55Ef5d3700eEC151d4Feff74214E7C90daBDE12B" } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/SmartCommitmentForwarder.json b/packages/contracts/deployments/polygon/SmartCommitmentForwarder.json index 5feb1719e..b3bd62266 100644 --- a/packages/contracts/deployments/polygon/SmartCommitmentForwarder.json +++ b/packages/contracts/deployments/polygon/SmartCommitmentForwarder.json @@ -214,6 +214,20 @@ ], "outputs": [] }, + { + "type": "function", + "name": "getLastUnpausedAt", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "uint256", + "name": "" + } + ] + }, { "type": "function", "name": "getLiquidationProtocolFeePercent", @@ -383,6 +397,6 @@ "blockHash": null, "blockNumber": null }, - "numDeployments": 2, + "numDeployments": 3, "implementation": "0xb9636C8b00a838B8b30502A2dD3bF18aa473AE0c" } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/TellerV2.json b/packages/contracts/deployments/polygon/TellerV2.json index 3507df599..3a9c0b96d 100644 --- a/packages/contracts/deployments/polygon/TellerV2.json +++ b/packages/contracts/deployments/polygon/TellerV2.json @@ -237,18 +237,6 @@ } ] }, - { - "type": "event", - "anonymous": false, - "name": "Paused", - "inputs": [ - { - "type": "address", - "name": "account", - "indexed": false - } - ] - }, { "type": "event", "anonymous": false, @@ -315,18 +303,6 @@ } ] }, - { - "type": "event", - "anonymous": false, - "name": "Unpaused", - "inputs": [ - { - "type": "address", - "name": "account", - "indexed": false - } - ] - }, { "type": "function", "name": "CURRENT_CODE_VERSION", @@ -388,19 +364,6 @@ } ] }, - { - "type": "function", - "name": "addPauser", - "constant": false, - "payable": false, - "inputs": [ - { - "type": "address", - "name": "_pauser" - } - ], - "outputs": [] - }, { "type": "function", "name": "approveMarketForwarder", @@ -969,6 +932,20 @@ } ] }, + { + "type": "function", + "name": "getProtocolPausingManager", + "constant": true, + "stateMutability": "view", + "payable": false, + "inputs": [], + "outputs": [ + { + "type": "address", + "name": "" + } + ] + }, { "type": "function", "name": "getRepaymentListenerForBid", @@ -1048,6 +1025,10 @@ { "type": "address", "name": "_escrowVault" + }, + { + "type": "address", + "name": "_protocolPausingManager" } ], "outputs": [] @@ -1109,25 +1090,6 @@ } ] }, - { - "type": "function", - "name": "isPauser", - "constant": true, - "stateMutability": "view", - "payable": false, - "inputs": [ - { - "type": "address", - "name": "_account" - } - ], - "outputs": [ - { - "type": "bool", - "name": "" - } - ] - }, { "type": "function", "name": "isPaymentLate", @@ -1345,20 +1307,6 @@ ], "outputs": [] }, - { - "type": "function", - "name": "liquidationsPaused", - "constant": true, - "stateMutability": "view", - "payable": false, - "inputs": [], - "outputs": [ - { - "type": "bool", - "name": "" - } - ] - }, { "type": "function", "name": "marketOwnerCancelBid", @@ -1400,55 +1348,6 @@ } ] }, - { - "type": "function", - "name": "pauseLiquidations", - "constant": false, - "payable": false, - "inputs": [], - "outputs": [] - }, - { - "type": "function", - "name": "pauseProtocol", - "constant": false, - "payable": false, - "inputs": [], - "outputs": [] - }, - { - "type": "function", - "name": "paused", - "constant": true, - "stateMutability": "view", - "payable": false, - "inputs": [], - "outputs": [ - { - "type": "bool", - "name": "" - } - ] - }, - { - "type": "function", - "name": "pauserRoleBearer", - "constant": true, - "stateMutability": "view", - "payable": false, - "inputs": [ - { - "type": "address", - "name": "" - } - ], - "outputs": [ - { - "type": "bool", - "name": "" - } - ] - }, { "type": "function", "name": "protocolFee", @@ -1463,19 +1362,6 @@ } ] }, - { - "type": "function", - "name": "removePauser", - "constant": false, - "payable": false, - "inputs": [ - { - "type": "address", - "name": "_pauser" - } - ], - "outputs": [] - }, { "type": "function", "name": "renounceMarketForwarder", @@ -1620,6 +1506,19 @@ ], "outputs": [] }, + { + "type": "function", + "name": "setProtocolPausingManager", + "constant": false, + "payable": false, + "inputs": [ + { + "type": "address", + "name": "_protocolPausingManager" + } + ], + "outputs": [] + }, { "type": "function", "name": "setRepaymentListenerForBid", @@ -1792,22 +1691,6 @@ ], "outputs": [] }, - { - "type": "function", - "name": "unpauseLiquidations", - "constant": false, - "payable": false, - "inputs": [], - "outputs": [] - }, - { - "type": "function", - "name": "unpauseProtocol", - "constant": false, - "payable": false, - "inputs": [], - "outputs": [] - }, { "type": "function", "name": "uris", @@ -1900,6 +1783,6 @@ "status": 1, "byzantium": true }, - "numDeployments": 14, + "numDeployments": 19, "implementation": "0xd177f4b8e348b4c56c2ac8e03b58e41b79351a7f" } \ No newline at end of file From 50d321574363909d40da02d495136c9d80ec5d58 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Tue, 15 Oct 2024 10:25:12 -0400 Subject: [PATCH 25/32] fix revert in deploy --- packages/contracts/.openzeppelin/polygon.json | 630 ++++++++++++++++++ packages/contracts/contracts/TellerV2.sol | 4 +- .../deployments/polygon/.migrations.json | 4 +- .../polygon/CollateralManager.json | 2 +- .../polygon/SmartCommitmentForwarder.json | 2 +- .../deployments/polygon/TellerV2.json | 2 +- 6 files changed, 637 insertions(+), 7 deletions(-) diff --git a/packages/contracts/.openzeppelin/polygon.json b/packages/contracts/.openzeppelin/polygon.json index a2c253f32..c38c65a7d 100644 --- a/packages/contracts/.openzeppelin/polygon.json +++ b/packages/contracts/.openzeppelin/polygon.json @@ -11687,6 +11687,636 @@ }, "namespaces": {} } + }, + "f65000183247be1ccbd3747e4fd5b3abb31d0aed7c721392f0a3c671219d86aa": { + "address": "0xF2F197D71Cd7C247af0d63F0b5c5D8745AA27Cdb", + "txHash": "0xc01081ec659ca0ed00a57a077a01dec1b61bdc6ccf67a2a0c97cb9862b636c33", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_protocolFee", + "offset": 0, + "slot": "101", + "type": "t_uint16", + "contract": "ProtocolFee", + "src": "contracts/ProtocolFee.sol:8" + }, + { + "label": "__paused", + "offset": 2, + "slot": "101", + "type": "t_bool", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:22" + }, + { + "label": "_protocolPausingManager", + "offset": 3, + "slot": "101", + "type": "t_address", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)48_storage", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:61" + }, + { + "label": "bidId", + "offset": 0, + "slot": "150", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:92" + }, + { + "label": "bids", + "offset": 0, + "slot": "151", + "type": "t_mapping(t_uint256,t_struct(Bid)9761_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:95" + }, + { + "label": "borrowerBids", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:98" + }, + { + "label": "__lenderVolumeFilled", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:101" + }, + { + "label": "__totalVolumeFilled", + "offset": 0, + "slot": "154", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:104" + }, + { + "label": "__lendingTokensSet", + "offset": 0, + "slot": "155", + "type": "t_struct(AddressSet)5563_storage", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:107" + }, + { + "label": "marketRegistry", + "offset": 0, + "slot": "157", + "type": "t_contract(IMarketRegistry)10634", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:109" + }, + { + "label": "reputationManager", + "offset": 0, + "slot": "158", + "type": "t_contract(IReputationManager)10721", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:110" + }, + { + "label": "_borrowerBidsActive", + "offset": 0, + "slot": "159", + "type": "t_mapping(t_address,t_struct(UintSet)5720_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:113" + }, + { + "label": "bidDefaultDuration", + "offset": 0, + "slot": "160", + "type": "t_mapping(t_uint256,t_uint32)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:115" + }, + { + "label": "bidExpirationTime", + "offset": 0, + "slot": "161", + "type": "t_mapping(t_uint256,t_uint32)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:116" + }, + { + "label": "lenderVolumeFilled", + "offset": 0, + "slot": "162", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:120" + }, + { + "label": "totalVolumeFilled", + "offset": 0, + "slot": "163", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:124" + }, + { + "label": "version", + "offset": 0, + "slot": "164", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:126" + }, + { + "label": "uris", + "offset": 0, + "slot": "165", + "type": "t_mapping(t_uint256,t_string_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:130" + }, + { + "label": "_trustedMarketForwarders", + "offset": 0, + "slot": "166", + "type": "t_mapping(t_uint256,t_address)", + "contract": "TellerV2Storage_G1", + "src": "contracts/TellerV2Storage.sol:135" + }, + { + "label": "_approvedForwarderSenders", + "offset": 0, + "slot": "167", + "type": "t_mapping(t_address,t_struct(AddressSet)5563_storage)", + "contract": "TellerV2Storage_G1", + "src": "contracts/TellerV2Storage.sol:137" + }, + { + "label": "lenderCommitmentForwarder", + "offset": 0, + "slot": "168", + "type": "t_address", + "contract": "TellerV2Storage_G2", + "src": "contracts/TellerV2Storage.sol:142" + }, + { + "label": "collateralManager", + "offset": 0, + "slot": "169", + "type": "t_contract(ICollateralManager)10099", + "contract": "TellerV2Storage_G3", + "src": "contracts/TellerV2Storage.sol:146" + }, + { + "label": "lenderManager", + "offset": 0, + "slot": "170", + "type": "t_contract(ILenderManager)10441", + "contract": "TellerV2Storage_G4", + "src": "contracts/TellerV2Storage.sol:151" + }, + { + "label": "bidPaymentCycleType", + "offset": 0, + "slot": "171", + "type": "t_mapping(t_uint256,t_enum(PaymentCycleType)12765)", + "contract": "TellerV2Storage_G4", + "src": "contracts/TellerV2Storage.sol:153" + }, + { + "label": "escrowVault", + "offset": 0, + "slot": "172", + "type": "t_contract(IEscrowVault)10419", + "contract": "TellerV2Storage_G5", + "src": "contracts/TellerV2Storage.sol:158" + }, + { + "label": "repaymentListenerForBid", + "offset": 0, + "slot": "173", + "type": "t_mapping(t_uint256,t_address)", + "contract": "TellerV2Storage_G6", + "src": "contracts/TellerV2Storage.sol:162" + }, + { + "label": "__pauserRoleBearer", + "offset": 0, + "slot": "174", + "type": "t_mapping(t_address,t_bool)", + "contract": "TellerV2Storage_G7", + "src": "contracts/TellerV2Storage.sol:166" + }, + { + "label": "__liquidationsPaused", + "offset": 0, + "slot": "175", + "type": "t_bool", + "contract": "TellerV2Storage_G7", + "src": "contracts/TellerV2Storage.sol:167" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_array(t_uint256)dyn_storage": { + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ICollateralManager)10099": { + "label": "contract ICollateralManager", + "numberOfBytes": "20" + }, + "t_contract(IERC20)1872": { + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IEscrowVault)10419": { + "label": "contract IEscrowVault", + "numberOfBytes": "20" + }, + "t_contract(ILenderManager)10441": { + "label": "contract ILenderManager", + "numberOfBytes": "20" + }, + "t_contract(IMarketRegistry)10634": { + "label": "contract IMarketRegistry", + "numberOfBytes": "20" + }, + "t_contract(IReputationManager)10721": { + "label": "contract IReputationManager", + "numberOfBytes": "20" + }, + "t_enum(BidState)9733": { + "label": "enum BidState", + "members": [ + "NONEXISTENT", + "PENDING", + "CANCELLED", + "ACCEPTED", + "PAID", + "LIQUIDATED", + "CLOSED" + ], + "numberOfBytes": "1" + }, + "t_enum(PaymentCycleType)12765": { + "label": "enum PaymentCycleType", + "members": [ + "Seconds", + "Monthly" + ], + "numberOfBytes": "1" + }, + "t_enum(PaymentType)12762": { + "label": "enum PaymentType", + "members": [ + "EMI", + "Bullet" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { + "label": "mapping(address => uint256[])", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(AddressSet)5563_storage)": { + "label": "mapping(address => struct EnumerableSet.AddressSet)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(UintSet)5720_storage)": { + "label": "mapping(address => struct EnumerableSet.UintSet)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_enum(PaymentCycleType)12765)": { + "label": "mapping(uint256 => enum PaymentCycleType)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_string_storage)": { + "label": "mapping(uint256 => string)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Bid)9761_storage)": { + "label": "mapping(uint256 => struct Bid)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint32)": { + "label": "mapping(uint256 => uint32)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)5563_storage": { + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)5248_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Bid)9761_storage": { + "label": "struct Bid", + "members": [ + { + "label": "borrower", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "receiver", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "lender", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "marketplaceId", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "_metadataURI", + "type": "t_bytes32", + "offset": 0, + "slot": "4" + }, + { + "label": "loanDetails", + "type": "t_struct(LoanDetails)9778_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "terms", + "type": "t_struct(Terms)9785_storage", + "offset": 0, + "slot": "10" + }, + { + "label": "state", + "type": "t_enum(BidState)9733", + "offset": 0, + "slot": "12" + }, + { + "label": "paymentType", + "type": "t_enum(PaymentType)12762", + "offset": 1, + "slot": "12" + } + ], + "numberOfBytes": "416" + }, + "t_struct(LoanDetails)9778_storage": { + "label": "struct LoanDetails", + "members": [ + { + "label": "lendingToken", + "type": "t_contract(IERC20)1872", + "offset": 0, + "slot": "0" + }, + { + "label": "principal", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "totalRepaid", + "type": "t_struct(Payment)9738_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "timestamp", + "type": "t_uint32", + "offset": 0, + "slot": "4" + }, + { + "label": "acceptedTimestamp", + "type": "t_uint32", + "offset": 4, + "slot": "4" + }, + { + "label": "lastRepaidTimestamp", + "type": "t_uint32", + "offset": 8, + "slot": "4" + }, + { + "label": "loanDuration", + "type": "t_uint32", + "offset": 12, + "slot": "4" + } + ], + "numberOfBytes": "160" + }, + "t_struct(Payment)9738_storage": { + "label": "struct Payment", + "members": [ + { + "label": "principal", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "interest", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)5248_storage": { + "label": "struct EnumerableSet.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Terms)9785_storage": { + "label": "struct Terms", + "members": [ + { + "label": "paymentCycleAmount", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "paymentCycle", + "type": "t_uint32", + "offset": 0, + "slot": "1" + }, + { + "label": "APR", + "type": "t_uint16", + "offset": 4, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(UintSet)5720_storage": { + "label": "struct EnumerableSet.UintSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)5248_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/contracts/contracts/TellerV2.sol b/packages/contracts/contracts/TellerV2.sol index 080d01ce2..8144c8582 100644 --- a/packages/contracts/contracts/TellerV2.sol +++ b/packages/contracts/contracts/TellerV2.sol @@ -251,10 +251,10 @@ contract TellerV2 is } */ - + function setProtocolPausingManager( address _protocolPausingManager - ) external onlyOwner reinitializer(10) { + ) external reinitializer(10) { _setProtocolPausingManager(_protocolPausingManager); diff --git a/packages/contracts/deployments/polygon/.migrations.json b/packages/contracts/deployments/polygon/.migrations.json index 4d6b7b269..b49bfa883 100644 --- a/packages/contracts/deployments/polygon/.migrations.json +++ b/packages/contracts/deployments/polygon/.migrations.json @@ -36,6 +36,6 @@ "lender-commitment-group-factory:upgrade-multihop": 1727465789, "smart-commitment-forwarder:upgrade-pausing": 1727811173, "protocol-pausing-manager:deploy": 1728941512, - "teller-v2:pausing-manager-upgrade": 1728942782, - "lender-commitment-group-beacon:upgrade": 1728942801 + "lender-commitment-group-beacon:upgrade": 1728942801, + "teller-v2:pausing-manager-upgrade": 1729002281 } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/CollateralManager.json b/packages/contracts/deployments/polygon/CollateralManager.json index e3f904cb9..b081bce8f 100644 --- a/packages/contracts/deployments/polygon/CollateralManager.json +++ b/packages/contracts/deployments/polygon/CollateralManager.json @@ -778,6 +778,6 @@ "status": 1, "byzantium": true }, - "numDeployments": 9, + "numDeployments": 10, "implementation": "0x48f4ddbc34a0df3b5ac2b13db4895fa980607aa9" } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/SmartCommitmentForwarder.json b/packages/contracts/deployments/polygon/SmartCommitmentForwarder.json index b3bd62266..4f87d46a7 100644 --- a/packages/contracts/deployments/polygon/SmartCommitmentForwarder.json +++ b/packages/contracts/deployments/polygon/SmartCommitmentForwarder.json @@ -397,6 +397,6 @@ "blockHash": null, "blockNumber": null }, - "numDeployments": 3, + "numDeployments": 4, "implementation": "0xb9636C8b00a838B8b30502A2dD3bF18aa473AE0c" } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/TellerV2.json b/packages/contracts/deployments/polygon/TellerV2.json index 3a9c0b96d..cf8ceea8a 100644 --- a/packages/contracts/deployments/polygon/TellerV2.json +++ b/packages/contracts/deployments/polygon/TellerV2.json @@ -1783,6 +1783,6 @@ "status": 1, "byzantium": true }, - "numDeployments": 19, + "numDeployments": 20, "implementation": "0xd177f4b8e348b4c56c2ac8e03b58e41b79351a7f" } \ No newline at end of file From ba7fe6d4ff26c66702b12cc9aefc1d4eebcb1fd9 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Tue, 15 Oct 2024 13:04:19 -0400 Subject: [PATCH 26/32] fix storage slots --- packages/contracts/.openzeppelin/polygon.json | 1256 +++++++++++++++++ .../pausing/HasProtocolPausingManager.sol | 3 +- .../deployments/polygon/.migrations.json | 3 +- .../deployments/polygon/TellerV2.json | 2 +- 4 files changed, 1261 insertions(+), 3 deletions(-) diff --git a/packages/contracts/.openzeppelin/polygon.json b/packages/contracts/.openzeppelin/polygon.json index c38c65a7d..eb1292ee0 100644 --- a/packages/contracts/.openzeppelin/polygon.json +++ b/packages/contracts/.openzeppelin/polygon.json @@ -12317,6 +12317,1262 @@ }, "namespaces": {} } + }, + "6ba87dc119ab12556997dc29b4961828867f4ab75f455fa88f4763efb8c43a32": { + "address": "0x84E2ab3177045aF218FaDF4Aa5d9708F6773d37f", + "txHash": "0xcfc87c82937487ea7bcb92d09cd053b2a83fdc17c758f33c883179b881045ef4", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_protocolFee", + "offset": 0, + "slot": "101", + "type": "t_uint16", + "contract": "ProtocolFee", + "src": "contracts/ProtocolFee.sol:8" + }, + { + "label": "__paused", + "offset": 2, + "slot": "101", + "type": "t_bool", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:22" + }, + { + "label": "_protocolPausingManager", + "offset": 3, + "slot": "101", + "type": "t_address", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)47_storage", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:61" + }, + { + "label": "bidId", + "offset": 0, + "slot": "149", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:92" + }, + { + "label": "bids", + "offset": 0, + "slot": "150", + "type": "t_mapping(t_uint256,t_struct(Bid)9761_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:95" + }, + { + "label": "borrowerBids", + "offset": 0, + "slot": "151", + "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:98" + }, + { + "label": "__lenderVolumeFilled", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:101" + }, + { + "label": "__totalVolumeFilled", + "offset": 0, + "slot": "153", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:104" + }, + { + "label": "__lendingTokensSet", + "offset": 0, + "slot": "154", + "type": "t_struct(AddressSet)5563_storage", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:107" + }, + { + "label": "marketRegistry", + "offset": 0, + "slot": "156", + "type": "t_contract(IMarketRegistry)10634", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:109" + }, + { + "label": "reputationManager", + "offset": 0, + "slot": "157", + "type": "t_contract(IReputationManager)10721", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:110" + }, + { + "label": "_borrowerBidsActive", + "offset": 0, + "slot": "158", + "type": "t_mapping(t_address,t_struct(UintSet)5720_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:113" + }, + { + "label": "bidDefaultDuration", + "offset": 0, + "slot": "159", + "type": "t_mapping(t_uint256,t_uint32)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:115" + }, + { + "label": "bidExpirationTime", + "offset": 0, + "slot": "160", + "type": "t_mapping(t_uint256,t_uint32)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:116" + }, + { + "label": "lenderVolumeFilled", + "offset": 0, + "slot": "161", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:120" + }, + { + "label": "totalVolumeFilled", + "offset": 0, + "slot": "162", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:124" + }, + { + "label": "version", + "offset": 0, + "slot": "163", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:126" + }, + { + "label": "uris", + "offset": 0, + "slot": "164", + "type": "t_mapping(t_uint256,t_string_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:130" + }, + { + "label": "_trustedMarketForwarders", + "offset": 0, + "slot": "165", + "type": "t_mapping(t_uint256,t_address)", + "contract": "TellerV2Storage_G1", + "src": "contracts/TellerV2Storage.sol:135" + }, + { + "label": "_approvedForwarderSenders", + "offset": 0, + "slot": "166", + "type": "t_mapping(t_address,t_struct(AddressSet)5563_storage)", + "contract": "TellerV2Storage_G1", + "src": "contracts/TellerV2Storage.sol:137" + }, + { + "label": "lenderCommitmentForwarder", + "offset": 0, + "slot": "167", + "type": "t_address", + "contract": "TellerV2Storage_G2", + "src": "contracts/TellerV2Storage.sol:142" + }, + { + "label": "collateralManager", + "offset": 0, + "slot": "168", + "type": "t_contract(ICollateralManager)10099", + "contract": "TellerV2Storage_G3", + "src": "contracts/TellerV2Storage.sol:146" + }, + { + "label": "lenderManager", + "offset": 0, + "slot": "169", + "type": "t_contract(ILenderManager)10441", + "contract": "TellerV2Storage_G4", + "src": "contracts/TellerV2Storage.sol:151" + }, + { + "label": "bidPaymentCycleType", + "offset": 0, + "slot": "170", + "type": "t_mapping(t_uint256,t_enum(PaymentCycleType)12765)", + "contract": "TellerV2Storage_G4", + "src": "contracts/TellerV2Storage.sol:153" + }, + { + "label": "escrowVault", + "offset": 0, + "slot": "171", + "type": "t_contract(IEscrowVault)10419", + "contract": "TellerV2Storage_G5", + "src": "contracts/TellerV2Storage.sol:158" + }, + { + "label": "repaymentListenerForBid", + "offset": 0, + "slot": "172", + "type": "t_mapping(t_uint256,t_address)", + "contract": "TellerV2Storage_G6", + "src": "contracts/TellerV2Storage.sol:162" + }, + { + "label": "__pauserRoleBearer", + "offset": 0, + "slot": "173", + "type": "t_mapping(t_address,t_bool)", + "contract": "TellerV2Storage_G7", + "src": "contracts/TellerV2Storage.sol:166" + }, + { + "label": "__liquidationsPaused", + "offset": 0, + "slot": "174", + "type": "t_bool", + "contract": "TellerV2Storage_G7", + "src": "contracts/TellerV2Storage.sol:167" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)47_storage": { + "label": "uint256[47]", + "numberOfBytes": "1504" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_array(t_uint256)dyn_storage": { + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ICollateralManager)10099": { + "label": "contract ICollateralManager", + "numberOfBytes": "20" + }, + "t_contract(IERC20)1872": { + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IEscrowVault)10419": { + "label": "contract IEscrowVault", + "numberOfBytes": "20" + }, + "t_contract(ILenderManager)10441": { + "label": "contract ILenderManager", + "numberOfBytes": "20" + }, + "t_contract(IMarketRegistry)10634": { + "label": "contract IMarketRegistry", + "numberOfBytes": "20" + }, + "t_contract(IReputationManager)10721": { + "label": "contract IReputationManager", + "numberOfBytes": "20" + }, + "t_enum(BidState)9733": { + "label": "enum BidState", + "members": [ + "NONEXISTENT", + "PENDING", + "CANCELLED", + "ACCEPTED", + "PAID", + "LIQUIDATED", + "CLOSED" + ], + "numberOfBytes": "1" + }, + "t_enum(PaymentCycleType)12765": { + "label": "enum PaymentCycleType", + "members": [ + "Seconds", + "Monthly" + ], + "numberOfBytes": "1" + }, + "t_enum(PaymentType)12762": { + "label": "enum PaymentType", + "members": [ + "EMI", + "Bullet" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { + "label": "mapping(address => uint256[])", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(AddressSet)5563_storage)": { + "label": "mapping(address => struct EnumerableSet.AddressSet)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(UintSet)5720_storage)": { + "label": "mapping(address => struct EnumerableSet.UintSet)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_enum(PaymentCycleType)12765)": { + "label": "mapping(uint256 => enum PaymentCycleType)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_string_storage)": { + "label": "mapping(uint256 => string)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Bid)9761_storage)": { + "label": "mapping(uint256 => struct Bid)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint32)": { + "label": "mapping(uint256 => uint32)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)5563_storage": { + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)5248_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Bid)9761_storage": { + "label": "struct Bid", + "members": [ + { + "label": "borrower", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "receiver", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "lender", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "marketplaceId", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "_metadataURI", + "type": "t_bytes32", + "offset": 0, + "slot": "4" + }, + { + "label": "loanDetails", + "type": "t_struct(LoanDetails)9778_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "terms", + "type": "t_struct(Terms)9785_storage", + "offset": 0, + "slot": "10" + }, + { + "label": "state", + "type": "t_enum(BidState)9733", + "offset": 0, + "slot": "12" + }, + { + "label": "paymentType", + "type": "t_enum(PaymentType)12762", + "offset": 1, + "slot": "12" + } + ], + "numberOfBytes": "416" + }, + "t_struct(LoanDetails)9778_storage": { + "label": "struct LoanDetails", + "members": [ + { + "label": "lendingToken", + "type": "t_contract(IERC20)1872", + "offset": 0, + "slot": "0" + }, + { + "label": "principal", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "totalRepaid", + "type": "t_struct(Payment)9738_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "timestamp", + "type": "t_uint32", + "offset": 0, + "slot": "4" + }, + { + "label": "acceptedTimestamp", + "type": "t_uint32", + "offset": 4, + "slot": "4" + }, + { + "label": "lastRepaidTimestamp", + "type": "t_uint32", + "offset": 8, + "slot": "4" + }, + { + "label": "loanDuration", + "type": "t_uint32", + "offset": 12, + "slot": "4" + } + ], + "numberOfBytes": "160" + }, + "t_struct(Payment)9738_storage": { + "label": "struct Payment", + "members": [ + { + "label": "principal", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "interest", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)5248_storage": { + "label": "struct EnumerableSet.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Terms)9785_storage": { + "label": "struct Terms", + "members": [ + { + "label": "paymentCycleAmount", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "paymentCycle", + "type": "t_uint32", + "offset": 0, + "slot": "1" + }, + { + "label": "APR", + "type": "t_uint16", + "offset": 4, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(UintSet)5720_storage": { + "label": "struct EnumerableSet.UintSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)5248_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "dea1836ef174de83fb65fa9d97c9e89f3367edcad5417d68202af4ecfe619375": { + "address": "0x97a51fc3B8C4182b6c0C0a0f905A8e4d42153947", + "txHash": "0xa2eb52b144bce09b4d419e89e9ed35f4c67e9ed514befb67fd96dc613e3e986c", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_protocolFee", + "offset": 0, + "slot": "101", + "type": "t_uint16", + "contract": "ProtocolFee", + "src": "contracts/ProtocolFee.sol:8" + }, + { + "label": "__paused", + "offset": 2, + "slot": "101", + "type": "t_bool", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:22" + }, + { + "label": "_protocolPausingManager", + "offset": 3, + "slot": "101", + "type": "t_address", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:24" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "HasProtocolPausingManager", + "src": "contracts/pausing/HasProtocolPausingManager.sol:61" + }, + { + "label": "bidId", + "offset": 0, + "slot": "151", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:92" + }, + { + "label": "bids", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_uint256,t_struct(Bid)9761_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:95" + }, + { + "label": "borrowerBids", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:98" + }, + { + "label": "__lenderVolumeFilled", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:101" + }, + { + "label": "__totalVolumeFilled", + "offset": 0, + "slot": "155", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:104" + }, + { + "label": "__lendingTokensSet", + "offset": 0, + "slot": "156", + "type": "t_struct(AddressSet)5563_storage", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:107" + }, + { + "label": "marketRegistry", + "offset": 0, + "slot": "158", + "type": "t_contract(IMarketRegistry)10634", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:109" + }, + { + "label": "reputationManager", + "offset": 0, + "slot": "159", + "type": "t_contract(IReputationManager)10721", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:110" + }, + { + "label": "_borrowerBidsActive", + "offset": 0, + "slot": "160", + "type": "t_mapping(t_address,t_struct(UintSet)5720_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:113" + }, + { + "label": "bidDefaultDuration", + "offset": 0, + "slot": "161", + "type": "t_mapping(t_uint256,t_uint32)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:115" + }, + { + "label": "bidExpirationTime", + "offset": 0, + "slot": "162", + "type": "t_mapping(t_uint256,t_uint32)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:116" + }, + { + "label": "lenderVolumeFilled", + "offset": 0, + "slot": "163", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:120" + }, + { + "label": "totalVolumeFilled", + "offset": 0, + "slot": "164", + "type": "t_mapping(t_address,t_uint256)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:124" + }, + { + "label": "version", + "offset": 0, + "slot": "165", + "type": "t_uint256", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:126" + }, + { + "label": "uris", + "offset": 0, + "slot": "166", + "type": "t_mapping(t_uint256,t_string_storage)", + "contract": "TellerV2Storage_G0", + "src": "contracts/TellerV2Storage.sol:130" + }, + { + "label": "_trustedMarketForwarders", + "offset": 0, + "slot": "167", + "type": "t_mapping(t_uint256,t_address)", + "contract": "TellerV2Storage_G1", + "src": "contracts/TellerV2Storage.sol:135" + }, + { + "label": "_approvedForwarderSenders", + "offset": 0, + "slot": "168", + "type": "t_mapping(t_address,t_struct(AddressSet)5563_storage)", + "contract": "TellerV2Storage_G1", + "src": "contracts/TellerV2Storage.sol:137" + }, + { + "label": "lenderCommitmentForwarder", + "offset": 0, + "slot": "169", + "type": "t_address", + "contract": "TellerV2Storage_G2", + "src": "contracts/TellerV2Storage.sol:142" + }, + { + "label": "collateralManager", + "offset": 0, + "slot": "170", + "type": "t_contract(ICollateralManager)10099", + "contract": "TellerV2Storage_G3", + "src": "contracts/TellerV2Storage.sol:146" + }, + { + "label": "lenderManager", + "offset": 0, + "slot": "171", + "type": "t_contract(ILenderManager)10441", + "contract": "TellerV2Storage_G4", + "src": "contracts/TellerV2Storage.sol:151" + }, + { + "label": "bidPaymentCycleType", + "offset": 0, + "slot": "172", + "type": "t_mapping(t_uint256,t_enum(PaymentCycleType)12765)", + "contract": "TellerV2Storage_G4", + "src": "contracts/TellerV2Storage.sol:153" + }, + { + "label": "escrowVault", + "offset": 0, + "slot": "173", + "type": "t_contract(IEscrowVault)10419", + "contract": "TellerV2Storage_G5", + "src": "contracts/TellerV2Storage.sol:158" + }, + { + "label": "repaymentListenerForBid", + "offset": 0, + "slot": "174", + "type": "t_mapping(t_uint256,t_address)", + "contract": "TellerV2Storage_G6", + "src": "contracts/TellerV2Storage.sol:162" + }, + { + "label": "__pauserRoleBearer", + "offset": 0, + "slot": "175", + "type": "t_mapping(t_address,t_bool)", + "contract": "TellerV2Storage_G7", + "src": "contracts/TellerV2Storage.sol:166" + }, + { + "label": "__liquidationsPaused", + "offset": 0, + "slot": "176", + "type": "t_bool", + "contract": "TellerV2Storage_G7", + "src": "contracts/TellerV2Storage.sol:167" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_array(t_uint256)dyn_storage": { + "label": "uint256[]", + "numberOfBytes": "32" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(ICollateralManager)10099": { + "label": "contract ICollateralManager", + "numberOfBytes": "20" + }, + "t_contract(IERC20)1872": { + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IEscrowVault)10419": { + "label": "contract IEscrowVault", + "numberOfBytes": "20" + }, + "t_contract(ILenderManager)10441": { + "label": "contract ILenderManager", + "numberOfBytes": "20" + }, + "t_contract(IMarketRegistry)10634": { + "label": "contract IMarketRegistry", + "numberOfBytes": "20" + }, + "t_contract(IReputationManager)10721": { + "label": "contract IReputationManager", + "numberOfBytes": "20" + }, + "t_enum(BidState)9733": { + "label": "enum BidState", + "members": [ + "NONEXISTENT", + "PENDING", + "CANCELLED", + "ACCEPTED", + "PAID", + "LIQUIDATED", + "CLOSED" + ], + "numberOfBytes": "1" + }, + "t_enum(PaymentCycleType)12765": { + "label": "enum PaymentCycleType", + "members": [ + "Seconds", + "Monthly" + ], + "numberOfBytes": "1" + }, + "t_enum(PaymentType)12762": { + "label": "enum PaymentType", + "members": [ + "EMI", + "Bullet" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { + "label": "mapping(address => uint256[])", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(AddressSet)5563_storage)": { + "label": "mapping(address => struct EnumerableSet.AddressSet)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_struct(UintSet)5720_storage)": { + "label": "mapping(address => struct EnumerableSet.UintSet)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_enum(PaymentCycleType)12765)": { + "label": "mapping(uint256 => enum PaymentCycleType)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_string_storage)": { + "label": "mapping(uint256 => string)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Bid)9761_storage)": { + "label": "mapping(uint256 => struct Bid)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint32)": { + "label": "mapping(uint256 => uint32)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(AddressSet)5563_storage": { + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)5248_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Bid)9761_storage": { + "label": "struct Bid", + "members": [ + { + "label": "borrower", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "receiver", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "lender", + "type": "t_address", + "offset": 0, + "slot": "2" + }, + { + "label": "marketplaceId", + "type": "t_uint256", + "offset": 0, + "slot": "3" + }, + { + "label": "_metadataURI", + "type": "t_bytes32", + "offset": 0, + "slot": "4" + }, + { + "label": "loanDetails", + "type": "t_struct(LoanDetails)9778_storage", + "offset": 0, + "slot": "5" + }, + { + "label": "terms", + "type": "t_struct(Terms)9785_storage", + "offset": 0, + "slot": "10" + }, + { + "label": "state", + "type": "t_enum(BidState)9733", + "offset": 0, + "slot": "12" + }, + { + "label": "paymentType", + "type": "t_enum(PaymentType)12762", + "offset": 1, + "slot": "12" + } + ], + "numberOfBytes": "416" + }, + "t_struct(LoanDetails)9778_storage": { + "label": "struct LoanDetails", + "members": [ + { + "label": "lendingToken", + "type": "t_contract(IERC20)1872", + "offset": 0, + "slot": "0" + }, + { + "label": "principal", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "totalRepaid", + "type": "t_struct(Payment)9738_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "timestamp", + "type": "t_uint32", + "offset": 0, + "slot": "4" + }, + { + "label": "acceptedTimestamp", + "type": "t_uint32", + "offset": 4, + "slot": "4" + }, + { + "label": "lastRepaidTimestamp", + "type": "t_uint32", + "offset": 8, + "slot": "4" + }, + { + "label": "loanDuration", + "type": "t_uint32", + "offset": 12, + "slot": "4" + } + ], + "numberOfBytes": "160" + }, + "t_struct(Payment)9738_storage": { + "label": "struct Payment", + "members": [ + { + "label": "principal", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "interest", + "type": "t_uint256", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)5248_storage": { + "label": "struct EnumerableSet.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Terms)9785_storage": { + "label": "struct Terms", + "members": [ + { + "label": "paymentCycleAmount", + "type": "t_uint256", + "offset": 0, + "slot": "0" + }, + { + "label": "paymentCycle", + "type": "t_uint32", + "offset": 0, + "slot": "1" + }, + { + "label": "APR", + "type": "t_uint16", + "offset": 4, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(UintSet)5720_storage": { + "label": "struct EnumerableSet.UintSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)5248_storage", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index 996babe09..d2183de38 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -19,6 +19,7 @@ abstract contract HasProtocolPausingManager { + //Both the bool and the address together take one storage slot bool private __paused;// .. Deprecated , handled by pausing manager address private _protocolPausingManager; // 20 bytes, gap will start at new slot @@ -58,5 +59,5 @@ abstract contract HasProtocolPausingManager * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[48] private __gap; + uint256[49] private __gap; } diff --git a/packages/contracts/deployments/polygon/.migrations.json b/packages/contracts/deployments/polygon/.migrations.json index b49bfa883..9da8430de 100644 --- a/packages/contracts/deployments/polygon/.migrations.json +++ b/packages/contracts/deployments/polygon/.migrations.json @@ -37,5 +37,6 @@ "smart-commitment-forwarder:upgrade-pausing": 1727811173, "protocol-pausing-manager:deploy": 1728941512, "lender-commitment-group-beacon:upgrade": 1728942801, - "teller-v2:pausing-manager-upgrade": 1729002281 + "teller-v2:pausing-manager-upgrade": 1729002281, + "teller-v2:pausing-manager-upgrade-v2": 1729011159 } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/TellerV2.json b/packages/contracts/deployments/polygon/TellerV2.json index cf8ceea8a..b0bfdfb12 100644 --- a/packages/contracts/deployments/polygon/TellerV2.json +++ b/packages/contracts/deployments/polygon/TellerV2.json @@ -1783,6 +1783,6 @@ "status": 1, "byzantium": true }, - "numDeployments": 20, + "numDeployments": 22, "implementation": "0xd177f4b8e348b4c56c2ac8e03b58e41b79351a7f" } \ No newline at end of file From 4199c8e67ce5117319a6dbca628463c983ccb7b6 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Thu, 17 Oct 2024 10:36:24 -0400 Subject: [PATCH 27/32] allow protocol pausers to pause individual pools --- .../LenderCommitmentGroup_Smart.sol | 27 ++++++++++++++++--- .../teller_v2/protocol_pausing_manager.ts | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol index 5becc3bc5..21520c933 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol @@ -20,6 +20,13 @@ import "../../../libraries/NumbersLib.sol"; import "../../../interfaces/uniswap/IUniswapV3Pool.sol"; + +import "../../../interfaces/IHasProtocolPausingManager.sol"; + +import "../../../interfaces/IProtocolPausingManager.sol"; + + + import "../../../interfaces/uniswap/IUniswapV3Factory.sol"; import "../../../interfaces/ISmartCommitmentForwarder.sol"; @@ -230,10 +237,22 @@ contract LenderCommitmentGroup_Smart is } - modifier onlyProtocolOwner() { + modifier onlyProtocolOwner() { require( msg.sender == Ownable(address(TELLER_V2)).owner(), - "Can only be called by TellerV2" + "Not Protocol Owner" + ); + _; + } + + modifier onlyOwnerOrProtocolPauser() { + + address pausingManager = IHasProtocolPausingManager( address(TELLER_V2) ).getProtocolPausingManager(); + + require( + IProtocolPausingManager( pausingManager ).isPauser(_msgSender()) + || msg.sender == owner() , + "Not Owner or Protocol Owner" ); _; } @@ -1018,14 +1037,14 @@ contract LenderCommitmentGroup_Smart is /** * @notice Lets the DAO/owner of the protocol implement an emergency stop mechanism. */ - function pauseLendingPool() public virtual onlyOwner whenNotPaused { + function pauseLendingPool() public virtual onlyOwnerOrProtocolPauser whenNotPaused { _pause(); } /** * @notice Lets the DAO/owner of the protocol undo a previously implemented emergency stop. */ - function unpauseLendingPool() public virtual onlyOwner whenPaused { + function unpauseLendingPool() public virtual onlyOwnerOrProtocolPauser whenPaused { setLastUnpausedAt(); _unpause(); } diff --git a/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts b/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts index cbc7cc3ca..e9ea5b98f 100644 --- a/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts +++ b/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts @@ -10,7 +10,7 @@ const deployFn: DeployFunction = async (hre) => { ], - //call init with no args + //call init with no args this doesnt work !! initArgs: [ ], From 2161616de8ffa77ba55b3dcb561eeb9af8401cd0 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Thu, 17 Oct 2024 10:36:49 -0400 Subject: [PATCH 28/32] msg sender --- .../LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol index 21520c933..3486fba3d 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol @@ -250,7 +250,7 @@ contract LenderCommitmentGroup_Smart is address pausingManager = IHasProtocolPausingManager( address(TELLER_V2) ).getProtocolPausingManager(); require( - IProtocolPausingManager( pausingManager ).isPauser(_msgSender()) + IProtocolPausingManager( pausingManager ).isPauser(msg.sender) || msg.sender == owner() , "Not Owner or Protocol Owner" ); From 678fb7226b377881cb118b379ee607576e5b2911 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Thu, 17 Oct 2024 10:52:14 -0400 Subject: [PATCH 29/32] comments --- .../LenderCommitmentGroup_Smart.sol | 9 ++++----- .../contracts/pausing/HasProtocolPausingManager.sol | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol index 3486fba3d..66f2c394a 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol @@ -245,13 +245,12 @@ contract LenderCommitmentGroup_Smart is _; } - modifier onlyOwnerOrProtocolPauser() { + modifier onlyProtocolPauser() { address pausingManager = IHasProtocolPausingManager( address(TELLER_V2) ).getProtocolPausingManager(); require( - IProtocolPausingManager( pausingManager ).isPauser(msg.sender) - || msg.sender == owner() , + IProtocolPausingManager( pausingManager ).isPauser(msg.sender) , "Not Owner or Protocol Owner" ); _; @@ -1037,14 +1036,14 @@ contract LenderCommitmentGroup_Smart is /** * @notice Lets the DAO/owner of the protocol implement an emergency stop mechanism. */ - function pauseLendingPool() public virtual onlyOwnerOrProtocolPauser whenNotPaused { + function pauseLendingPool() public virtual onlyProtocolPauser whenNotPaused { _pause(); } /** * @notice Lets the DAO/owner of the protocol undo a previously implemented emergency stop. */ - function unpauseLendingPool() public virtual onlyOwnerOrProtocolPauser whenPaused { + function unpauseLendingPool() public virtual onlyProtocolPauser whenPaused { setLastUnpausedAt(); _unpause(); } diff --git a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol index d2183de38..64ab5127f 100644 --- a/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol +++ b/packages/contracts/contracts/pausing/HasProtocolPausingManager.sol @@ -20,7 +20,7 @@ abstract contract HasProtocolPausingManager //Both the bool and the address together take one storage slot - bool private __paused;// .. Deprecated , handled by pausing manager + bool private __paused;// .. Deprecated , handled by pausing manager now address private _protocolPausingManager; // 20 bytes, gap will start at new slot @@ -31,7 +31,7 @@ abstract contract HasProtocolPausingManager _; } - //rename to when protocol not paused ? + modifier whenProtocolNotPaused() { require(! IProtocolPausingManager(_protocolPausingManager). protocolPaused(), "Protocol paused" ); @@ -39,7 +39,7 @@ abstract contract HasProtocolPausingManager } - //onlyinitializing? + function _setProtocolPausingManager(address protocolPausingManager) internal { _protocolPausingManager = protocolPausingManager ; } From 19babf30eb3d278b2c0f9ce14ffa39ab5d56a2f4 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Thu, 17 Oct 2024 11:31:46 -0400 Subject: [PATCH 30/32] mod --- .../LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol index 66f2c394a..d1cccd61f 100644 --- a/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol +++ b/packages/contracts/contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol @@ -261,6 +261,7 @@ contract LenderCommitmentGroup_Smart is _; } + modifier whenForwarderNotPaused() { require( PausableUpgradeable(address(SMART_COMMITMENT_FORWARDER)).paused() == false , "Smart Commitment Forwarder is paused"); From 41d57aa4a41a881ec916ef9030d47504aee0ba1b Mon Sep 17 00:00:00 2001 From: Admazzola Date: Thu, 17 Oct 2024 11:38:14 -0400 Subject: [PATCH 31/32] propose upgrade --- packages/contracts/.openzeppelin/polygon.json | 373 ++++++++++++++++++ .../deployments/polygon/.migrations.json | 4 +- .../polygon/LenderCommitmentGroupBeacon.json | 2 +- 3 files changed, 376 insertions(+), 3 deletions(-) diff --git a/packages/contracts/.openzeppelin/polygon.json b/packages/contracts/.openzeppelin/polygon.json index eb1292ee0..1b4d80a2d 100644 --- a/packages/contracts/.openzeppelin/polygon.json +++ b/packages/contracts/.openzeppelin/polygon.json @@ -13573,6 +13573,379 @@ }, "namespaces": {} } + }, + "dffab5dfedaf53c268d39a24a18d9dca23a5efcda9dff375d2d510bea2bc8631": { + "address": "0x98c1A3E3C0eDfef8db0f1525B07F92d4DFD4ac71", + "txHash": "0x8f490a73c322ecfa89985f2264fe86ea321818aad2fe81788af301a843d85103", + "layout": { + "solcVersion": "0.8.9", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_paused", + "offset": 0, + "slot": "101", + "type": "t_bool", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:29" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "PausableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol:116" + }, + { + "label": "UNISWAP_V3_POOL", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:104" + }, + { + "label": "poolSharesToken", + "offset": 0, + "slot": "152", + "type": "t_contract(LenderCommitmentGroupShares)8998", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:106" + }, + { + "label": "principalToken", + "offset": 0, + "slot": "153", + "type": "t_contract(IERC20)3917", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:108" + }, + { + "label": "collateralToken", + "offset": 0, + "slot": "154", + "type": "t_contract(IERC20)3917", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:109" + }, + { + "label": "_uniswapPoolFee", + "offset": 20, + "slot": "154", + "type": "t_uint24", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:110" + }, + { + "label": "marketId", + "offset": 0, + "slot": "155", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:112" + }, + { + "label": "totalPrincipalTokensCommitted", + "offset": 0, + "slot": "156", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:115" + }, + { + "label": "totalPrincipalTokensWithdrawn", + "offset": 0, + "slot": "157", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:116" + }, + { + "label": "totalPrincipalTokensLended", + "offset": 0, + "slot": "158", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:118" + }, + { + "label": "totalPrincipalTokensRepaid", + "offset": 0, + "slot": "159", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:119" + }, + { + "label": "totalInterestCollected", + "offset": 0, + "slot": "160", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:123" + }, + { + "label": "liquidityThresholdPercent", + "offset": 0, + "slot": "161", + "type": "t_uint16", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:125" + }, + { + "label": "collateralRatio", + "offset": 2, + "slot": "161", + "type": "t_uint16", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:126" + }, + { + "label": "_twapInterval", + "offset": 4, + "slot": "161", + "type": "t_uint32", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:128" + }, + { + "label": "maxLoanDuration", + "offset": 8, + "slot": "161", + "type": "t_uint32", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:129" + }, + { + "label": "interestRateLowerBound", + "offset": 12, + "slot": "161", + "type": "t_uint16", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:130" + }, + { + "label": "interestRateUpperBound", + "offset": 14, + "slot": "161", + "type": "t_uint16", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:131" + }, + { + "label": "poolSharesPreparedToWithdrawForLender", + "offset": 0, + "slot": "162", + "type": "t_mapping(t_address,t_uint256)", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:136" + }, + { + "label": "poolSharesPreparedTimestamp", + "offset": 0, + "slot": "163", + "type": "t_mapping(t_address,t_uint256)", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:137" + }, + { + "label": "activeBids", + "offset": 0, + "slot": "164", + "type": "t_mapping(t_uint256,t_bool)", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:142" + }, + { + "label": "tokenDifferenceFromLiquidations", + "offset": 0, + "slot": "165", + "type": "t_int256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:146" + }, + { + "label": "firstDepositMade", + "offset": 0, + "slot": "166", + "type": "t_bool", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:148" + }, + { + "label": "withdrawlDelayTimeSeconds", + "offset": 0, + "slot": "167", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:149" + }, + { + "label": "poolOracleRoutes", + "offset": 0, + "slot": "168", + "type": "t_array(t_struct(PoolRouteConfig)15082_storage)dyn_storage", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:151" + }, + { + "label": "maxPrincipalPerCollateralAmount", + "offset": 0, + "slot": "169", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:154" + }, + { + "label": "lastUnpausedAt", + "offset": 0, + "slot": "170", + "type": "t_uint256", + "contract": "LenderCommitmentGroup_Smart", + "src": "contracts/LenderCommitmentForwarder/extensions/LenderCommitmentGroup/LenderCommitmentGroup_Smart.sol:157" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(PoolRouteConfig)15082_storage)dyn_storage": { + "label": "struct IUniswapPricingLibrary.PoolRouteConfig[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)3917": { + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(LenderCommitmentGroupShares)8998": { + "label": "contract LenderCommitmentGroupShares", + "numberOfBytes": "20" + }, + "t_int256": { + "label": "int256", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_bool)": { + "label": "mapping(uint256 => bool)", + "numberOfBytes": "32" + }, + "t_struct(PoolRouteConfig)15082_storage": { + "label": "struct IUniswapPricingLibrary.PoolRouteConfig", + "members": [ + { + "label": "pool", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "zeroForOne", + "type": "t_bool", + "offset": 20, + "slot": "0" + }, + { + "label": "twapInterval", + "type": "t_uint32", + "offset": 21, + "slot": "0" + }, + { + "label": "token0Decimals", + "type": "t_uint256", + "offset": 0, + "slot": "1" + }, + { + "label": "token1Decimals", + "type": "t_uint256", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint24": { + "label": "uint24", + "numberOfBytes": "3" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } } } } diff --git a/packages/contracts/deployments/polygon/.migrations.json b/packages/contracts/deployments/polygon/.migrations.json index 9da8430de..d9ddb4a28 100644 --- a/packages/contracts/deployments/polygon/.migrations.json +++ b/packages/contracts/deployments/polygon/.migrations.json @@ -36,7 +36,7 @@ "lender-commitment-group-factory:upgrade-multihop": 1727465789, "smart-commitment-forwarder:upgrade-pausing": 1727811173, "protocol-pausing-manager:deploy": 1728941512, - "lender-commitment-group-beacon:upgrade": 1728942801, "teller-v2:pausing-manager-upgrade": 1729002281, - "teller-v2:pausing-manager-upgrade-v2": 1729011159 + "teller-v2:pausing-manager-upgrade-v2": 1729011159, + "lender-commitment-group-beacon:upgrade": 1729179210 } \ No newline at end of file diff --git a/packages/contracts/deployments/polygon/LenderCommitmentGroupBeacon.json b/packages/contracts/deployments/polygon/LenderCommitmentGroupBeacon.json index 3e5a7f019..3bca16c62 100644 --- a/packages/contracts/deployments/polygon/LenderCommitmentGroupBeacon.json +++ b/packages/contracts/deployments/polygon/LenderCommitmentGroupBeacon.json @@ -1399,6 +1399,6 @@ } ], "receipt": {}, - "numDeployments": 8, + "numDeployments": 9, "implementation": "0x55Ef5d3700eEC151d4Feff74214E7C90daBDE12B" } \ No newline at end of file From 93ec658f0d4dac7872eac47008312e23bcaa10e0 Mon Sep 17 00:00:00 2001 From: Admazzola Date: Thu, 17 Oct 2024 11:57:00 -0400 Subject: [PATCH 32/32] comment --- packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts b/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts index e9ea5b98f..c8b71a66f 100644 --- a/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts +++ b/packages/contracts/deploy/teller_v2/protocol_pausing_manager.ts @@ -10,7 +10,7 @@ const deployFn: DeployFunction = async (hre) => { ], - //call init with no args this doesnt work !! + //call init with no args this works fine initArgs: [ ],