Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 16049052 | 1203 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Morpho
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GNU AGPLv3 pragma solidity 0.8.13; import "./MorphoGovernance.sol"; /// @title Morpho. /// @author Morpho Labs. /// @custom:contact [email protected] /// @notice Main Morpho contract handling user interactions and pool interactions. contract Morpho is MorphoGovernance { using SafeTransferLib for ERC20; using DelegateCall for address; using WadRayMath for uint256; /// EVENTS /// /// @notice Emitted when a user claims rewards. /// @param _user The address of the claimer. /// @param _amountClaimed The amount of reward token claimed. /// @param _traded Whether or not the pool tokens are traded against Morpho tokens. event RewardsClaimed(address indexed _user, uint256 _amountClaimed, bool indexed _traded); /// ERRORS /// /// @notice Thrown when claiming rewards is paused. error ClaimRewardsPaused(); /// EXTERNAL /// /// @notice Supplies underlying tokens to a specific market. /// @dev `msg.sender` must have approved Morpho's contract to spend the underlying `_amount`. /// @param _poolToken The address of the market the user wants to interact with. /// @param _amount The amount of token (in underlying) to supply. function supply(address _poolToken, uint256 _amount) external nonReentrant isMarketCreatedAndNotPausedNorPartiallyPaused(_poolToken) { _supply(_poolToken, msg.sender, _amount, defaultMaxGasForMatching.supply); } /// @notice Supplies underlying tokens to a specific market, on behalf of a given user. /// @dev `msg.sender` must have approved Morpho's contract to spend the underlying `_amount`. /// @param _poolToken The address of the market the user wants to interact with. /// @param _onBehalf The address of the account whose positions will be updated. /// @param _amount The amount of token (in underlying) to supply. function supply( address _poolToken, address _onBehalf, uint256 _amount ) external nonReentrant isMarketCreatedAndNotPausedNorPartiallyPaused(_poolToken) { _supply(_poolToken, _onBehalf, _amount, defaultMaxGasForMatching.supply); } /// @notice Supplies underlying tokens to a specific market, on behalf of a given user, /// specifying a gas threshold at which to cut the matching engine. /// @dev `msg.sender` must have approved Morpho's contract to spend the underlying `_amount`. /// @param _poolToken The address of the market the user wants to interact with. /// @param _onBehalf The address of the account whose positions will be updated. /// @param _amount The amount of token (in underlying) to supply. /// @param _maxGasForMatching The gas threshold at which to stop the matching engine. function supply( address _poolToken, address _onBehalf, uint256 _amount, uint256 _maxGasForMatching ) external nonReentrant isMarketCreatedAndNotPausedNorPartiallyPaused(_poolToken) { _supply(_poolToken, _onBehalf, _amount, _maxGasForMatching); } /// @notice Borrows underlying tokens from a specific market. /// @param _poolToken The address of the market the user wants to interact with. /// @param _amount The amount of token (in underlying). function borrow(address _poolToken, uint256 _amount) external nonReentrant isMarketCreatedAndNotPausedNorPartiallyPaused(_poolToken) { _borrow(_poolToken, _amount, defaultMaxGasForMatching.borrow); } /// @notice Borrows underlying tokens from a specific market, specifying a gas threshold at which to stop the matching engine. /// @param _poolToken The address of the market the user wants to interact with. /// @param _amount The amount of token (in underlying). /// @param _maxGasForMatching The gas threshold at which to stop the matching engine. function borrow( address _poolToken, uint256 _amount, uint256 _maxGasForMatching ) external nonReentrant isMarketCreatedAndNotPausedNorPartiallyPaused(_poolToken) { _borrow(_poolToken, _amount, _maxGasForMatching); } /// @notice Withdraws underlying tokens from a specific market. /// @param _poolToken The address of the market the user wants to interact with. /// @param _amount The amount of tokens (in underlying) to withdraw from supply. function withdraw(address _poolToken, uint256 _amount) external nonReentrant isMarketCreatedAndNotPaused(_poolToken) { _withdraw(_poolToken, _amount, msg.sender, defaultMaxGasForMatching.withdraw); } /// @notice Withdraws underlying tokens from a specific market. /// @param _poolToken The address of the market the user wants to interact with. /// @param _amount The amount of tokens (in underlying) to withdraw from supply. /// @param _receiver The address to send withdrawn tokens to. function withdraw( address _poolToken, uint256 _amount, address _receiver ) external nonReentrant isMarketCreatedAndNotPaused(_poolToken) { _withdraw(_poolToken, _amount, _receiver, defaultMaxGasForMatching.withdraw); } /// @notice Repays the debt of the sender, up to the amount provided. /// @dev `msg.sender` must have approved Morpho's contract to spend the underlying `_amount`. /// @param _poolToken The address of the market the user wants to interact with. /// @param _amount The amount of token (in underlying) to repay from borrow. function repay(address _poolToken, uint256 _amount) external nonReentrant isMarketCreatedAndNotPaused(_poolToken) { _repay(_poolToken, msg.sender, _amount, defaultMaxGasForMatching.repay); } /// @notice Repays debt of a given user, up to the amount provided. /// @dev `msg.sender` must have approved Morpho's contract to spend the underlying `_amount`. /// @param _poolToken The address of the market the user wants to interact with. /// @param _onBehalf The address of the account whose positions will be updated. /// @param _amount The amount of token (in underlying) to repay from borrow. function repay( address _poolToken, address _onBehalf, uint256 _amount ) external nonReentrant isMarketCreatedAndNotPaused(_poolToken) { _repay(_poolToken, _onBehalf, _amount, defaultMaxGasForMatching.repay); } /// @notice Liquidates a position. /// @param _poolTokenBorrowed The address of the pool token the liquidator wants to repay. /// @param _poolTokenCollateral The address of the collateral pool token the liquidator wants to seize. /// @param _borrower The address of the borrower to liquidate. /// @param _amount The amount of token (in underlying) to repay. function liquidate( address _poolTokenBorrowed, address _poolTokenCollateral, address _borrower, uint256 _amount ) external nonReentrant isMarketCreatedAndNotPaused(_poolTokenBorrowed) isMarketCreatedAndNotPaused(_poolTokenCollateral) { address(exitPositionsManager).functionDelegateCall( abi.encodeWithSelector( IExitPositionsManager.liquidateLogic.selector, _poolTokenBorrowed, _poolTokenCollateral, _borrower, _amount ) ); } /// @notice Claims rewards for the given assets. /// @param _assets The assets to claim rewards from (aToken or variable debt token). /// @param _tradeForMorphoToken Whether or not to trade reward tokens for MORPHO tokens. /// @return claimedAmount The amount of rewards claimed (in reward token). function claimRewards(address[] calldata _assets, bool _tradeForMorphoToken) external nonReentrant returns (uint256 claimedAmount) { if (isClaimRewardsPaused) revert ClaimRewardsPaused(); claimedAmount = rewardsManager.claimRewards(aaveIncentivesController, _assets, msg.sender); if (claimedAmount > 0) { if (_tradeForMorphoToken) { aaveIncentivesController.claimRewards( _assets, claimedAmount, address(incentivesVault) ); incentivesVault.tradeRewardTokensForMorphoTokens(msg.sender, claimedAmount); } else aaveIncentivesController.claimRewards(_assets, claimedAmount, msg.sender); emit RewardsClaimed(msg.sender, claimedAmount, _tradeForMorphoToken); } } /// INTERNAL /// function _supply( address _poolToken, address _onBehalf, uint256 _amount, uint256 _maxGasForMatching ) internal { address(entryPositionsManager).functionDelegateCall( abi.encodeWithSelector( IEntryPositionsManager.supplyLogic.selector, _poolToken, msg.sender, _onBehalf, _amount, _maxGasForMatching ) ); } function _borrow( address _poolToken, uint256 _amount, uint256 _maxGasForMatching ) internal { address(entryPositionsManager).functionDelegateCall( abi.encodeWithSelector( IEntryPositionsManager.borrowLogic.selector, _poolToken, _amount, _maxGasForMatching ) ); } function _withdraw( address _poolToken, uint256 _amount, address _receiver, uint256 _maxGasForMatching ) internal { address(exitPositionsManager).functionDelegateCall( abi.encodeWithSelector( IExitPositionsManager.withdrawLogic.selector, _poolToken, _amount, msg.sender, _receiver, _maxGasForMatching ) ); } function _repay( address _poolToken, address _onBehalf, uint256 _amount, uint256 _maxGasForMatching ) internal { address(exitPositionsManager).functionDelegateCall( abi.encodeWithSelector( IExitPositionsManager.repayLogic.selector, _poolToken, msg.sender, _onBehalf, _amount, _maxGasForMatching ) ); } }
// SPDX-License-Identifier: GNU AGPLv3 pragma solidity 0.8.13; import "@rari-capital/solmate/src/utils/SafeTransferLib.sol"; import "./MorphoUtils.sol"; /// @title MorphoGovernance. /// @author Morpho Labs. /// @custom:contact [email protected] /// @notice Governance functions for Morpho. abstract contract MorphoGovernance is MorphoUtils { using ReserveConfiguration for DataTypes.ReserveConfigurationMap; using PercentageMath for uint256; using SafeTransferLib for ERC20; using DelegateCall for address; using WadRayMath for uint256; /// EVENTS /// /// @notice Emitted when a new `defaultMaxGasForMatching` is set. /// @param _defaultMaxGasForMatching The new `defaultMaxGasForMatching`. event DefaultMaxGasForMatchingSet(Types.MaxGasForMatching _defaultMaxGasForMatching); /// @notice Emitted when a new value for `maxSortedUsers` is set. /// @param _newValue The new value of `maxSortedUsers`. event MaxSortedUsersSet(uint256 _newValue); /// @notice Emitted when the address of the `treasuryVault` is set. /// @param _newTreasuryVaultAddress The new address of the `treasuryVault`. event TreasuryVaultSet(address indexed _newTreasuryVaultAddress); /// @notice Emitted when the address of the `incentivesVault` is set. /// @param _newIncentivesVaultAddress The new address of the `incentivesVault`. event IncentivesVaultSet(address indexed _newIncentivesVaultAddress); /// @notice Emitted when the `entryPositionsManager` is set. /// @param _entryPositionsManager The new address of the `entryPositionsManager`. event EntryPositionsManagerSet(address indexed _entryPositionsManager); /// @notice Emitted when the `exitPositionsManager` is set. /// @param _exitPositionsManager The new address of the `exitPositionsManager`. event ExitPositionsManagerSet(address indexed _exitPositionsManager); /// @notice Emitted when the `rewardsManager` is set. /// @param _newRewardsManagerAddress The new address of the `rewardsManager`. event RewardsManagerSet(address indexed _newRewardsManagerAddress); /// @notice Emitted when the `interestRatesManager` is set. /// @param _interestRatesManager The new address of the `interestRatesManager`. event InterestRatesSet(address indexed _interestRatesManager); /// @notice Emitted when the address of the `aaveIncentivesController` is set. /// @param _aaveIncentivesController The new address of the `aaveIncentivesController`. event AaveIncentivesControllerSet(address indexed _aaveIncentivesController); /// @notice Emitted when the `reserveFactor` is set. /// @param _poolToken The address of the concerned market. /// @param _newValue The new value of the `reserveFactor`. event ReserveFactorSet(address indexed _poolToken, uint16 _newValue); /// @notice Emitted when the `p2pIndexCursor` is set. /// @param _poolToken The address of the concerned market. /// @param _newValue The new value of the `p2pIndexCursor`. event P2PIndexCursorSet(address indexed _poolToken, uint16 _newValue); /// @notice Emitted when a reserve fee is claimed. /// @param _poolToken The address of the concerned market. /// @param _amountClaimed The amount of reward token claimed. event ReserveFeeClaimed(address indexed _poolToken, uint256 _amountClaimed); /// @notice Emitted when the value of `isP2PDisabled` is set. /// @param _poolToken The address of the concerned market. /// @param _isP2PDisabled The new value of `_isP2PDisabled` adopted. event P2PStatusSet(address indexed _poolToken, bool _isP2PDisabled); /// @notice Emitted when a market is paused or unpaused. /// @param _poolToken The address of the concerned market. /// @param _newStatus The new pause status of the market. event PauseStatusSet(address indexed _poolToken, bool _newStatus); /// @notice Emitted when a market is partially paused or unpaused. /// @param _poolToken The address of the concerned market. /// @param _newStatus The new partial pause status of the market. event PartialPauseStatusSet(address indexed _poolToken, bool _newStatus); /// @notice Emitted when claiming rewards is paused or unpaused. /// @param _newStatus The new claiming rewards status. event ClaimRewardsPauseStatusSet(bool _newStatus); /// @notice Emitted when a new market is created. /// @param _poolToken The address of the market that has been created. /// @param _reserveFactor The reserve factor set for this market. /// @param _poolToken The P2P index cursor set for this market. event MarketCreated(address indexed _poolToken, uint16 _reserveFactor, uint16 _p2pIndexCursor); /// ERRORS /// /// @notice Thrown when the market is not listed on Aave. error MarketIsNotListedOnAave(); /// @notice Thrown when the input is above the max basis points value (100%). error ExceedsMaxBasisPoints(); /// @notice Thrown when the market is already created. error MarketAlreadyCreated(); /// @notice Thrown when trying to set the max sorted users to 0. error MaxSortedUsersCannotBeZero(); /// @notice Thrown when the number of markets will exceed the bitmask's capacity. error MaxNumberOfMarkets(); /// @notice Thrown when the address is the zero address. error ZeroAddress(); /// UPGRADE /// /// @notice Initializes the Morpho contract. /// @param _entryPositionsManager The `entryPositionsManager`. /// @param _exitPositionsManager The `exitPositionsManager`. /// @param _interestRatesManager The `interestRatesManager`. /// @param _lendingPoolAddressesProvider The `addressesProvider`. /// @param _defaultMaxGasForMatching The `defaultMaxGasForMatching`. /// @param _maxSortedUsers The `_maxSortedUsers`. function initialize( IEntryPositionsManager _entryPositionsManager, IExitPositionsManager _exitPositionsManager, IInterestRatesManager _interestRatesManager, ILendingPoolAddressesProvider _lendingPoolAddressesProvider, Types.MaxGasForMatching memory _defaultMaxGasForMatching, uint256 _maxSortedUsers ) external initializer { if (_maxSortedUsers == 0) revert MaxSortedUsersCannotBeZero(); __ReentrancyGuard_init(); __Ownable_init(); interestRatesManager = _interestRatesManager; entryPositionsManager = _entryPositionsManager; exitPositionsManager = _exitPositionsManager; addressesProvider = _lendingPoolAddressesProvider; pool = ILendingPool(addressesProvider.getLendingPool()); defaultMaxGasForMatching = _defaultMaxGasForMatching; maxSortedUsers = _maxSortedUsers; } /// GOVERNANCE /// /// @notice Sets `maxSortedUsers`. /// @param _newMaxSortedUsers The new `maxSortedUsers` value. function setMaxSortedUsers(uint256 _newMaxSortedUsers) external onlyOwner { if (_newMaxSortedUsers == 0) revert MaxSortedUsersCannotBeZero(); maxSortedUsers = _newMaxSortedUsers; emit MaxSortedUsersSet(_newMaxSortedUsers); } /// @notice Sets `defaultMaxGasForMatching`. /// @param _defaultMaxGasForMatching The new `defaultMaxGasForMatching`. function setDefaultMaxGasForMatching(Types.MaxGasForMatching memory _defaultMaxGasForMatching) external onlyOwner { defaultMaxGasForMatching = _defaultMaxGasForMatching; emit DefaultMaxGasForMatchingSet(_defaultMaxGasForMatching); } /// @notice Sets the `entryPositionsManager`. /// @param _entryPositionsManager The new `entryPositionsManager`. function setEntryPositionsManager(IEntryPositionsManager _entryPositionsManager) external onlyOwner { if (address(_entryPositionsManager) == address(0)) revert ZeroAddress(); entryPositionsManager = _entryPositionsManager; emit EntryPositionsManagerSet(address(_entryPositionsManager)); } /// @notice Sets the `exitPositionsManager`. /// @param _exitPositionsManager The new `exitPositionsManager`. function setExitPositionsManager(IExitPositionsManager _exitPositionsManager) external onlyOwner { if (address(_exitPositionsManager) == address(0)) revert ZeroAddress(); exitPositionsManager = _exitPositionsManager; emit ExitPositionsManagerSet(address(_exitPositionsManager)); } /// @notice Sets the `interestRatesManager`. /// @param _interestRatesManager The new `interestRatesManager` contract. function setInterestRatesManager(IInterestRatesManager _interestRatesManager) external onlyOwner { if (address(_interestRatesManager) == address(0)) revert ZeroAddress(); interestRatesManager = _interestRatesManager; emit InterestRatesSet(address(_interestRatesManager)); } /// @notice Sets the `rewardsManager`. /// @param _rewardsManager The new `rewardsManager`. function setRewardsManager(IRewardsManager _rewardsManager) external onlyOwner { rewardsManager = _rewardsManager; emit RewardsManagerSet(address(_rewardsManager)); } /// @notice Sets the `treasuryVault`. /// @param _treasuryVault The address of the new `treasuryVault`. function setTreasuryVault(address _treasuryVault) external onlyOwner { treasuryVault = _treasuryVault; emit TreasuryVaultSet(_treasuryVault); } /// @notice Sets the `aaveIncentivesController`. /// @param _aaveIncentivesController The address of the `aaveIncentivesController`. function setAaveIncentivesController(address _aaveIncentivesController) external onlyOwner { aaveIncentivesController = IAaveIncentivesController(_aaveIncentivesController); emit AaveIncentivesControllerSet(_aaveIncentivesController); } /// @notice Sets the `incentivesVault`. /// @param _incentivesVault The new `incentivesVault`. function setIncentivesVault(IIncentivesVault _incentivesVault) external onlyOwner { incentivesVault = _incentivesVault; emit IncentivesVaultSet(address(_incentivesVault)); } /// @notice Sets the `reserveFactor`. /// @param _poolToken The market on which to set the `_newReserveFactor`. /// @param _newReserveFactor The proportion of the interest earned by users sent to the DAO, in basis point. function setReserveFactor(address _poolToken, uint16 _newReserveFactor) external onlyOwner isMarketCreated(_poolToken) { if (_newReserveFactor > MAX_BASIS_POINTS) revert ExceedsMaxBasisPoints(); _updateIndexes(_poolToken); market[_poolToken].reserveFactor = _newReserveFactor; emit ReserveFactorSet(_poolToken, _newReserveFactor); } /// @notice Sets a new peer-to-peer cursor. /// @param _poolToken The address of the market to update. /// @param _p2pIndexCursor The new peer-to-peer cursor. function setP2PIndexCursor(address _poolToken, uint16 _p2pIndexCursor) external onlyOwner isMarketCreated(_poolToken) { if (_p2pIndexCursor > MAX_BASIS_POINTS) revert ExceedsMaxBasisPoints(); _updateIndexes(_poolToken); market[_poolToken].p2pIndexCursor = _p2pIndexCursor; emit P2PIndexCursorSet(_poolToken, _p2pIndexCursor); } /// @notice Sets the pause status for all markets. /// @param _newStatus The new status to set. function setPauseStatusForAllMarkets(bool _newStatus) external onlyOwner { uint256 numberOfMarketsCreated = marketsCreated.length; for (uint256 i; i < numberOfMarketsCreated; ) { address poolToken = marketsCreated[i]; market[poolToken].isPaused = _newStatus; emit PauseStatusSet(poolToken, _newStatus); unchecked { ++i; } } } /// @notice Sets the pause status on a specific market in case of emergency. /// @param _poolToken The address of the market to pause/unpause. /// @param _newStatus The new status to set. function setPauseStatus(address _poolToken, bool _newStatus) external onlyOwner isMarketCreated(_poolToken) { market[_poolToken].isPaused = _newStatus; emit PauseStatusSet(_poolToken, _newStatus); } /// @notice Sets the partial pause status on a specific market in case of emergency. /// @param _poolToken The address of the market to partially pause/unpause. /// @param _newStatus The new status to set. function setPartialPauseStatus(address _poolToken, bool _newStatus) external onlyOwner isMarketCreated(_poolToken) { market[_poolToken].isPartiallyPaused = _newStatus; emit PartialPauseStatusSet(_poolToken, _newStatus); } /// @notice Sets the peer-to-peer disable status. /// @param _poolToken The address of the market of which to enable/disable peer-to-peer matching. /// @param _newStatus The new status to set. function setP2PDisabledStatus(address _poolToken, bool _newStatus) external onlyOwner isMarketCreated(_poolToken) { market[_poolToken].isP2PDisabled = _newStatus; emit P2PStatusSet(_poolToken, _newStatus); } /// @notice Sets the pause status on claiming rewards. /// @param _newStatus The new status to set. function setClaimRewardsPauseStatus(bool _newStatus) external onlyOwner { isClaimRewardsPaused = _newStatus; emit ClaimRewardsPauseStatusSet(_newStatus); } /// @notice Sets a market's asset as collateral. /// @param _poolToken The address of the market to (un)set as collateral. /// @param _newStatus The new status to set. function setAssetAsCollateral(address _poolToken, bool _newStatus) external onlyOwner isMarketCreated(_poolToken) { pool.setUserUseReserveAsCollateral(market[_poolToken].underlyingToken, _newStatus); } /// @notice Increases peer-to-peer deltas, to put some liquidity back on the pool. /// @dev The current Morpho supply on the pool might not be enough to borrow `_amount` before resuppling it. /// In this case, consider calling multiple times this function. /// @param _poolToken The address of the market on which to increase deltas. /// @param _amount The maximum amount to add to the deltas (in underlying). function increaseP2PDeltas(address _poolToken, uint256 _amount) external onlyOwner { address(exitPositionsManager).functionDelegateCall( abi.encodeWithSelector( IExitPositionsManager.increaseP2PDeltasLogic.selector, _poolToken, _amount ) ); } /// @notice Transfers the protocol reserve fee to the DAO. /// @param _poolTokens The addresses of the pool token addresses on which to claim the reserve fee. /// @param _amounts The list of amounts of underlying tokens to claim on each market. function claimToTreasury(address[] calldata _poolTokens, uint256[] calldata _amounts) external onlyOwner { if (treasuryVault == address(0)) revert ZeroAddress(); uint256 numberOfMarkets = _poolTokens.length; for (uint256 i; i < numberOfMarkets; ++i) { address poolToken = _poolTokens[i]; Types.Market memory market = market[poolToken]; if (!market.isCreated || market.isPaused || market.isPartiallyPaused) continue; ERC20 underlyingToken = ERC20(market.underlyingToken); uint256 underlyingBalance = underlyingToken.balanceOf(address(this)); if (underlyingBalance == 0) continue; uint256 toClaim = Math.min(_amounts[i], underlyingBalance); underlyingToken.safeTransfer(treasuryVault, toClaim); emit ReserveFeeClaimed(poolToken, toClaim); } } /// @notice Creates a new market to borrow/supply in. /// @param _underlyingToken The underlying token address. /// @param _reserveFactor The reserve factor to set on this market. /// @param _p2pIndexCursor The peer-to-peer index cursor to set on this market. function createMarket( address _underlyingToken, uint16 _reserveFactor, uint16 _p2pIndexCursor ) external onlyOwner { if (marketsCreated.length >= MAX_NB_OF_MARKETS) revert MaxNumberOfMarkets(); if (_underlyingToken == address(0)) revert ZeroAddress(); if (_p2pIndexCursor > MAX_BASIS_POINTS || _reserveFactor > MAX_BASIS_POINTS) revert ExceedsMaxBasisPoints(); if (!pool.getConfiguration(_underlyingToken).getActive()) revert MarketIsNotListedOnAave(); address poolToken = pool.getReserveData(_underlyingToken).aTokenAddress; if (market[poolToken].isCreated) revert MarketAlreadyCreated(); p2pSupplyIndex[poolToken] = WadRayMath.RAY; p2pBorrowIndex[poolToken] = WadRayMath.RAY; Types.PoolIndexes storage poolIndexes = poolIndexes[poolToken]; poolIndexes.lastUpdateTimestamp = uint32(block.timestamp); poolIndexes.poolSupplyIndex = uint112(pool.getReserveNormalizedIncome(_underlyingToken)); poolIndexes.poolBorrowIndex = uint112( pool.getReserveNormalizedVariableDebt(_underlyingToken) ); market[poolToken] = Types.Market({ underlyingToken: _underlyingToken, reserveFactor: _reserveFactor, p2pIndexCursor: _p2pIndexCursor, isCreated: true, isPaused: false, isPartiallyPaused: false, isP2PDisabled: false }); borrowMask[poolToken] = ONE << (marketsCreated.length << 1); marketsCreated.push(poolToken); ERC20(_underlyingToken).safeApprove(address(pool), type(uint256).max); emit MarketCreated(poolToken, _reserveFactor, _p2pIndexCursor); } }
// SPDX-License-Identifier: GNU AGPLv3 pragma solidity 0.8.13; import "./interfaces/aave/ILendingPool.sol"; import "./interfaces/IEntryPositionsManager.sol"; import "./interfaces/IExitPositionsManager.sol"; import "./interfaces/IInterestRatesManager.sol"; import "./interfaces/IIncentivesVault.sol"; import "./interfaces/IRewardsManager.sol"; import "@morpho-dao/morpho-data-structures/HeapOrdering.sol"; import "./libraries/Types.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /// @title MorphoStorage. /// @author Morpho Labs. /// @custom:contact [email protected] /// @notice All storage variables used in Morpho contracts. abstract contract MorphoStorage is OwnableUpgradeable, ReentrancyGuardUpgradeable { /// GLOBAL STORAGE /// uint8 public constant NO_REFERRAL_CODE = 0; uint8 public constant VARIABLE_INTEREST_MODE = 2; uint16 public constant MAX_BASIS_POINTS = 10_000; // 100% in basis points. uint256 public constant DEFAULT_LIQUIDATION_CLOSE_FACTOR = 5_000; // 50% in basis points. uint256 public constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1e18; // Health factor below which the positions can be liquidated. uint256 public constant MAX_NB_OF_MARKETS = 128; bytes32 public constant BORROWING_MASK = 0x5555555555555555555555555555555555555555555555555555555555555555; bytes32 public constant ONE = 0x0000000000000000000000000000000000000000000000000000000000000001; bool public isClaimRewardsPaused; // Whether claiming rewards is paused or not. uint256 public maxSortedUsers; // The max number of users to sort in the data structure. Types.MaxGasForMatching public defaultMaxGasForMatching; // The default max gas to consume within loops in matching engine functions. /// POSITIONS STORAGE /// mapping(address => HeapOrdering.HeapArray) internal suppliersInP2P; // For a given market, the suppliers in peer-to-peer. mapping(address => HeapOrdering.HeapArray) internal suppliersOnPool; // For a given market, the suppliers on Aave. mapping(address => HeapOrdering.HeapArray) internal borrowersInP2P; // For a given market, the borrowers in peer-to-peer. mapping(address => HeapOrdering.HeapArray) internal borrowersOnPool; // For a given market, the borrowers on Aave. mapping(address => mapping(address => Types.SupplyBalance)) public supplyBalanceInOf; // For a given market, the supply balance of a user. aToken -> user -> balances. mapping(address => mapping(address => Types.BorrowBalance)) public borrowBalanceInOf; // For a given market, the borrow balance of a user. aToken -> user -> balances. mapping(address => bytes32) public userMarkets; // The markets entered by a user as a bitmask. /// MARKETS STORAGE /// address[] internal marketsCreated; // Keeps track of the created markets. mapping(address => uint256) public p2pSupplyIndex; // Current index from supply peer-to-peer unit to underlying (in ray). mapping(address => uint256) public p2pBorrowIndex; // Current index from borrow peer-to-peer unit to underlying (in ray). mapping(address => Types.PoolIndexes) public poolIndexes; // Last pool index stored. mapping(address => Types.Market) public market; // Market information. mapping(address => Types.Delta) public deltas; // Delta parameters for each market. mapping(address => bytes32) public borrowMask; // Borrow mask of the given market, shift left to get the supply mask. /// CONTRACTS AND ADDRESSES /// ILendingPoolAddressesProvider public addressesProvider; IAaveIncentivesController public aaveIncentivesController; ILendingPool public pool; IEntryPositionsManager public entryPositionsManager; IExitPositionsManager public exitPositionsManager; IInterestRatesManager public interestRatesManager; IIncentivesVault public incentivesVault; IRewardsManager public rewardsManager; address public treasuryVault; /// CONSTRUCTOR /// /// @notice Constructs the contract. /// @dev The contract is automatically marked as initialized when deployed so that nobody can highjack the implementation contract. constructor() initializer {} }
// SPDX-License-Identifier: GNU AGPLv3 pragma solidity 0.8.13; import "./interfaces/aave/IPriceOracleGetter.sol"; import "./interfaces/aave/IAToken.sol"; import "./libraries/aave/ReserveConfiguration.sol"; import "@morpho-dao/morpho-utils/DelegateCall.sol"; import "@morpho-dao/morpho-utils/math/PercentageMath.sol"; import "@morpho-dao/morpho-utils/math/WadRayMath.sol"; import "@morpho-dao/morpho-utils/math/Math.sol"; import "./MorphoStorage.sol"; /// @title MorphoUtils. /// @author Morpho Labs. /// @custom:contact [email protected] /// @notice Modifiers, getters and other util functions for Morpho. abstract contract MorphoUtils is MorphoStorage { using ReserveConfiguration for DataTypes.ReserveConfigurationMap; using HeapOrdering for HeapOrdering.HeapArray; using PercentageMath for uint256; using DelegateCall for address; using WadRayMath for uint256; using Math for uint256; /// ERRORS /// /// @notice Thrown when the market is not created yet. error MarketNotCreated(); /// @notice Thrown when the market is paused. error MarketPaused(); /// MODIFIERS /// /// @notice Prevents to update a market not created yet. /// @param _poolToken The address of the market to check. modifier isMarketCreated(address _poolToken) { if (!market[_poolToken].isCreated) revert MarketNotCreated(); _; } /// @notice Prevents a user to trigger a function when market is not created or paused. /// @param _poolToken The address of the market to check. modifier isMarketCreatedAndNotPaused(address _poolToken) { Types.Market memory market = market[_poolToken]; if (!market.isCreated) revert MarketNotCreated(); if (market.isPaused) revert MarketPaused(); _; } /// @notice Prevents a user to trigger a function when market is not created or paused or partial paused. /// @param _poolToken The address of the market to check. modifier isMarketCreatedAndNotPausedNorPartiallyPaused(address _poolToken) { Types.Market memory market = market[_poolToken]; if (!market.isCreated) revert MarketNotCreated(); if (market.isPaused || market.isPartiallyPaused) revert MarketPaused(); _; } /// EXTERNAL /// /// @notice Returns all created markets. /// @return marketsCreated_ The list of market addresses. function getMarketsCreated() external view returns (address[] memory) { return marketsCreated; } /// @notice Gets the head of the data structure on a specific market (for UI). /// @param _poolToken The address of the market from which to get the head. /// @param _positionType The type of user from which to get the head. /// @return head The head in the data structure. function getHead(address _poolToken, Types.PositionType _positionType) external view returns (address head) { if (_positionType == Types.PositionType.SUPPLIERS_IN_P2P) head = suppliersInP2P[_poolToken].getHead(); else if (_positionType == Types.PositionType.SUPPLIERS_ON_POOL) head = suppliersOnPool[_poolToken].getHead(); else if (_positionType == Types.PositionType.BORROWERS_IN_P2P) head = borrowersInP2P[_poolToken].getHead(); else head = borrowersOnPool[_poolToken].getHead(); // Borrowers on pool. } /// @notice Gets the next user after `_user` in the data structure on a specific market (for UI). /// @dev Beware that this function does not give the next account susceptible to get matched, /// nor the next account with highest liquidity. Use it only to go through every account. /// @param _poolToken The address of the market from which to get the user. /// @param _positionType The type of user from which to get the next user. /// @param _user The address of the user from which to get the next user. /// @return next The next user in the data structure. function getNext( address _poolToken, Types.PositionType _positionType, address _user ) external view returns (address next) { if (_positionType == Types.PositionType.SUPPLIERS_IN_P2P) next = suppliersInP2P[_poolToken].getNext(_user); else if (_positionType == Types.PositionType.SUPPLIERS_ON_POOL) next = suppliersOnPool[_poolToken].getNext(_user); else if (_positionType == Types.PositionType.BORROWERS_IN_P2P) next = borrowersInP2P[_poolToken].getNext(_user); else next = borrowersOnPool[_poolToken].getNext(_user); // Borrowers on pool. } /// @notice Updates the peer-to-peer indexes and pool indexes (only stored locally). /// @param _poolToken The address of the market to update. function updateIndexes(address _poolToken) external isMarketCreated(_poolToken) { _updateIndexes(_poolToken); } /// INTERNAL /// /// @dev Returns if a user has been borrowing or supplying on a given market. /// @param _userMarkets The bitmask encoding the markets entered by the user. /// @param _borrowMask The borrow mask of the market to check. /// @return True if the user has been supplying or borrowing on this market, false otherwise. function _isSupplyingOrBorrowing(bytes32 _userMarkets, bytes32 _borrowMask) internal pure returns (bool) { return _userMarkets & (_borrowMask | (_borrowMask << 1)) != 0; } /// @dev Returns if a user is borrowing on a given market. /// @param _userMarkets The bitmask encoding the markets entered by the user. /// @param _borrowMask The borrow mask of the market to check. /// @return True if the user has been borrowing on this market, false otherwise. function _isBorrowing(bytes32 _userMarkets, bytes32 _borrowMask) internal pure returns (bool) { return _userMarkets & _borrowMask != 0; } /// @dev Returns if a user is supplying on a given market. /// @param _userMarkets The bitmask encoding the markets entered by the user. /// @param _borrowMask The borrow mask of the market to check. /// @return True if the user has been supplying on this market, false otherwise. function _isSupplying(bytes32 _userMarkets, bytes32 _borrowMask) internal pure returns (bool) { return _userMarkets & (_borrowMask << 1) != 0; } /// @dev Returns if a user has been borrowing from any market. /// @param _userMarkets The bitmask encoding the markets entered by the user. /// @return True if the user has been borrowing on any market, false otherwise. function _isBorrowingAny(bytes32 _userMarkets) internal pure returns (bool) { return _userMarkets & BORROWING_MASK != 0; } /// @dev Returns if a user is borrowing on a given market and supplying on another given market. /// @param _userMarkets The bitmask encoding the markets entered by the user. /// @param _borrowedBorrowMask The borrow mask of the market to check whether the user is borrowing. /// @param _suppliedBorrowMask The borrow mask of the market to check whether the user is supplying. /// @return True if the user is borrowing on the given market and supplying on the other given market, false otherwise. function _isBorrowingAndSupplying( bytes32 _userMarkets, bytes32 _borrowedBorrowMask, bytes32 _suppliedBorrowMask ) internal pure returns (bool) { bytes32 targetMask = _borrowedBorrowMask | (_suppliedBorrowMask << 1); return _userMarkets & targetMask == targetMask; } /// @notice Sets if the user is borrowing on a market. /// @param _user The user to set for. /// @param _borrowMask The borrow mask of the market to mark as borrowed. /// @param _borrowing True if the user is borrowing, false otherwise. function _setBorrowing( address _user, bytes32 _borrowMask, bool _borrowing ) internal { if (_borrowing) userMarkets[_user] |= _borrowMask; else userMarkets[_user] &= ~_borrowMask; } /// @notice Sets if the user is supplying on a market. /// @param _user The user to set for. /// @param _borrowMask The borrow mask of the market to mark as supplied. /// @param _supplying True if the user is supplying, false otherwise. function _setSupplying( address _user, bytes32 _borrowMask, bool _supplying ) internal { if (_supplying) userMarkets[_user] |= _borrowMask << 1; else userMarkets[_user] &= ~(_borrowMask << 1); } /// @dev Updates the peer-to-peer indexes and pool indexes (only stored locally). /// @param _poolToken The address of the market to update. function _updateIndexes(address _poolToken) internal { address(interestRatesManager).functionDelegateCall( abi.encodeWithSelector(interestRatesManager.updateIndexes.selector, _poolToken) ); } /// @dev Returns the supply balance of `_user` in the `_poolToken` market. /// @dev Note: Compute the result with the index stored and not the most up to date one. /// @param _user The address of the user. /// @param _poolToken The market where to get the supply amount. /// @return The supply balance of the user (in underlying). function _getUserSupplyBalanceInOf(address _poolToken, address _user) internal view returns (uint256) { Types.SupplyBalance memory userSupplyBalance = supplyBalanceInOf[_poolToken][_user]; return userSupplyBalance.inP2P.rayMul(p2pSupplyIndex[_poolToken]) + userSupplyBalance.onPool.rayMul(poolIndexes[_poolToken].poolSupplyIndex); } /// @dev Returns the borrow balance of `_user` in the `_poolToken` market. /// @dev Note: Compute the result with the index stored and not the most up to date one. /// @param _user The address of the user. /// @param _poolToken The market where to get the borrow amount. /// @return The borrow balance of the user (in underlying). function _getUserBorrowBalanceInOf(address _poolToken, address _user) internal view returns (uint256) { Types.BorrowBalance memory userBorrowBalance = borrowBalanceInOf[_poolToken][_user]; return userBorrowBalance.inP2P.rayMul(p2pBorrowIndex[_poolToken]) + userBorrowBalance.onPool.rayMul(poolIndexes[_poolToken].poolBorrowIndex); } /// @dev Calculates the value of the collateral. /// @param _poolToken The pool token to calculate the value for. /// @param _user The user address. /// @param _underlyingPrice The underlying price. /// @param _tokenUnit The token unit. function _collateralValue( address _poolToken, address _user, uint256 _underlyingPrice, uint256 _tokenUnit ) internal view returns (uint256 collateral) { collateral = (_getUserSupplyBalanceInOf(_poolToken, _user) * _underlyingPrice) / _tokenUnit; } /// @dev Calculates the value of the debt. /// @param _poolToken The pool token to calculate the value for. /// @param _user The user address. /// @param _underlyingPrice The underlying price. /// @param _tokenUnit The token unit. function _debtValue( address _poolToken, address _user, uint256 _underlyingPrice, uint256 _tokenUnit ) internal view returns (uint256 debt) { debt = (_getUserBorrowBalanceInOf(_poolToken, _user) * _underlyingPrice).divUp(_tokenUnit); } /// @dev Calculates the total value of the collateral, debt, and LTV/LT value depending on the calculation type. /// @param _user The user address. /// @param _poolToken The pool token that is being borrowed or withdrawn. /// @param _amountWithdrawn The amount that is being withdrawn. /// @param _amountBorrowed The amount that is being borrowed. /// @return values The struct containing health factor, collateral, debt, ltv, liquidation threshold values. function _liquidityData( address _user, address _poolToken, uint256 _amountWithdrawn, uint256 _amountBorrowed ) internal returns (Types.LiquidityData memory values) { IPriceOracleGetter oracle = IPriceOracleGetter(addressesProvider.getPriceOracle()); Types.AssetLiquidityData memory assetData; Types.LiquidityStackVars memory vars; vars.poolTokensLength = marketsCreated.length; vars.userMarkets = userMarkets[_user]; for (uint256 i; i < vars.poolTokensLength; ++i) { vars.poolToken = marketsCreated[i]; vars.borrowMask = borrowMask[vars.poolToken]; if (!_isSupplyingOrBorrowing(vars.userMarkets, vars.borrowMask)) continue; vars.underlyingToken = market[vars.poolToken].underlyingToken; vars.underlyingPrice = oracle.getAssetPrice(vars.underlyingToken); if (vars.poolToken != _poolToken) _updateIndexes(vars.poolToken); (assetData.ltv, assetData.liquidationThreshold, , assetData.decimals, ) = pool .getConfiguration(vars.underlyingToken) .getParamsMemory(); unchecked { assetData.tokenUnit = 10**assetData.decimals; } if (_isBorrowing(vars.userMarkets, vars.borrowMask)) { values.debt += _debtValue( vars.poolToken, _user, vars.underlyingPrice, assetData.tokenUnit ); } // Cache current asset collateral value. uint256 assetCollateralValue; if (_isSupplying(vars.userMarkets, vars.borrowMask)) { assetCollateralValue = _collateralValue( vars.poolToken, _user, vars.underlyingPrice, assetData.tokenUnit ); values.collateral += assetCollateralValue; // Calculate LTV for borrow. values.maxDebt += assetCollateralValue.percentMul(assetData.ltv); } // Update debt variable for borrowed token. if (_poolToken == vars.poolToken && _amountBorrowed > 0) values.debt += (_amountBorrowed * vars.underlyingPrice).divUp(assetData.tokenUnit); // Update LT variable for withdraw. if (assetCollateralValue > 0) values.liquidationThreshold += assetCollateralValue.percentMul( assetData.liquidationThreshold ); // Subtract withdrawn amount from liquidation threshold and collateral. if (_poolToken == vars.poolToken && _amountWithdrawn > 0) { uint256 withdrawn = (_amountWithdrawn * vars.underlyingPrice) / assetData.tokenUnit; values.collateral -= withdrawn; values.liquidationThreshold -= withdrawn.percentMul(assetData.liquidationThreshold); values.maxDebt -= withdrawn.percentMul(assetData.ltv); } } } }
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;
interface IEntryPositionsManager {
function supplyLogic(
address _poolToken,
address _supplier,
address _onBehalf,
uint256 _amount,
uint256 _maxGasForMatching
) external;
function borrowLogic(
address _poolToken,
uint256 _amount,
uint256 _maxGasForMatching
) external;
}// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;
interface IExitPositionsManager {
function withdrawLogic(
address _poolToken,
uint256 _amount,
address _supplier,
address _receiver,
uint256 _maxGasForMatching
) external;
function repayLogic(
address _poolToken,
address _repayer,
address _onBehalf,
uint256 _amount,
uint256 _maxGasForMatching
) external;
function liquidateLogic(
address _poolTokenBorrowed,
address _poolTokenCollateral,
address _borrower,
uint256 _amount
) external;
function increaseP2PDeltasLogic(address _poolToken, uint256 _amount) external;
}// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;
import "./IOracle.sol";
interface IIncentivesVault {
function isPaused() external view returns (bool);
function bonus() external view returns (uint256);
function MAX_BASIS_POINTS() external view returns (uint256);
function incentivesTreasuryVault() external view returns (address);
function oracle() external view returns (IOracle);
function setOracle(IOracle _newOracle) external;
function setIncentivesTreasuryVault(address _newIncentivesTreasuryVault) external;
function setBonus(uint256 _newBonus) external;
function setPauseStatus(bool _newStatus) external;
function transferTokensToDao(address _token, uint256 _amount) external;
function tradeRewardTokensForMorphoTokens(address _to, uint256 _amount) external;
}// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;
interface IInterestRatesManager {
function ST_ETH() external view returns (address);
function ST_ETH_BASE_REBASE_INDEX() external view returns (uint256);
function updateIndexes(address _marketAddress) external;
}// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;
interface IOracle {
function consult(uint256 _amountIn) external returns (uint256);
}// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;
import "./aave/IAaveIncentivesController.sol";
interface IRewardsManager {
function initialize(address _morpho) external;
function getUserIndex(address, address) external returns (uint256);
function getUserUnclaimedRewards(address[] calldata, address) external view returns (uint256);
function claimRewards(
IAaveIncentivesController _aaveIncentivesController,
address[] calldata,
address
) external returns (uint256);
function updateUserAssetAndAccruedRewards(
IAaveIncentivesController _aaveIncentivesController,
address _user,
address _asset,
uint256 _userBalance,
uint256 _totalBalance
) external;
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
import {IERC20} from "./IERC20.sol";
import {IScaledBalanceToken} from "./IScaledBalanceToken.sol";
interface IAToken is IERC20, IScaledBalanceToken {
/**
* @dev Emitted after the mint action
* @param from The address performing the mint
* @param value The amount being
* @param index The new liquidity index of the reserve
**/
event Mint(address indexed from, uint256 value, uint256 index);
/**
* @dev Mints `amount` aTokens to `user`
* @param user The address receiving the minted tokens
* @param amount The amount of tokens getting minted
* @param index The new liquidity index of the reserve
* @return `true` if the the previous balance of the user was 0
*/
function mint(
address user,
uint256 amount,
uint256 index
) external returns (bool);
/**
* @dev Emitted after aTokens are burned
* @param from The owner of the aTokens, getting them burned
* @param target The address that will receive the underlying
* @param value The amount being burned
* @param index The new liquidity index of the reserve
**/
event Burn(address indexed from, address indexed target, uint256 value, uint256 index);
/**
* @dev Emitted during the transfer action
* @param from The user whose tokens are being transferred
* @param to The recipient
* @param value The amount being transferred
* @param index The new liquidity index of the reserve
**/
event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index);
/**
* @dev Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying`
* @param user The owner of the aTokens, getting them burned
* @param receiverOfUnderlying The address that will receive the underlying
* @param amount The amount being burned
* @param index The new liquidity index of the reserve
**/
function burn(
address user,
address receiverOfUnderlying,
uint256 amount,
uint256 index
) external;
/**
* @dev Mints aTokens to the reserve treasury
* @param amount The amount of tokens getting minted
* @param index The new liquidity index of the reserve
*/
function mintToTreasury(uint256 amount, uint256 index) external;
/**
* @dev Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken
* @param from The address getting liquidated, current owner of the aTokens
* @param to The recipient
* @param value The amount of tokens getting transferred
**/
function transferOnLiquidation(
address from,
address to,
uint256 value
) external;
/**
* @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer
* assets in borrow(), withdraw() and flashLoan()
* @param user The recipient of the aTokens
* @param amount The amount getting transferred
* @return The amount transferred
**/
function transferUnderlyingTo(address user, uint256 amount) external returns (uint256);
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
interface IAaveDistributionManager {
event AssetConfigUpdated(address indexed asset, uint256 emission);
event AssetIndexUpdated(address indexed asset, uint256 index);
event UserIndexUpdated(address indexed user, address indexed asset, uint256 index);
event DistributionEndUpdated(uint256 newDistributionEnd);
/**
* @dev Sets the end date for the distribution
* @param distributionEnd The end date timestamp
**/
function setDistributionEnd(uint256 distributionEnd) external;
/**
* @dev Gets the end date for the distribution
* @return The end of the distribution
**/
function getDistributionEnd() external view returns (uint256);
/**
* @dev for backwards compatibility with the previous DistributionManager used
* @return The end of the distribution
**/
function DISTRIBUTION_END() external view returns (uint256);
/**
* @dev Returns the data of an user on a distribution
* @param user Address of the user
* @param asset The address of the reference asset of the distribution
* @return The new index
**/
function getUserAssetData(address user, address asset) external view returns (uint256);
/**
* @dev Returns the configuration of the distribution for a certain asset
* @param asset The address of the reference asset of the distribution
* @return The asset index, the emission per second and the last updated timestamp
**/
function getAssetData(address asset)
external
view
returns (
uint256,
uint256,
uint256
);
}
interface IAaveIncentivesController is IAaveDistributionManager {
event RewardsAccrued(address indexed user, uint256 amount);
event RewardsClaimed(
address indexed user,
address indexed to,
address indexed claimer,
uint256 amount
);
event ClaimerSet(address indexed user, address indexed claimer);
/**
* @dev Whitelists an address to claim the rewards on behalf of another address
* @param user The address of the user
* @param claimer The address of the claimer
*/
function setClaimer(address user, address claimer) external;
/**
* @dev Returns the whitelisted claimer for a certain address (0x0 if not set)
* @param user The address of the user
* @return The claimer address
*/
function getClaimer(address user) external view returns (address);
/**
* @dev Configure assets for a certain rewards emission
* @param assets The assets to incentivize
* @param emissionsPerSecond The emission for each asset
*/
function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond)
external;
/**
* @dev Called by the corresponding asset on any update that affects the rewards distribution
* @param asset The address of the user
* @param userBalance The balance of the user of the asset in the lending pool
* @param totalSupply The total supply of the asset in the lending pool
**/
function handleAction(
address asset,
uint256 userBalance,
uint256 totalSupply
) external;
/**
* @dev Returns the total of rewards of an user, already accrued + not yet accrued
* @param user The address of the user
* @return The rewards
**/
function getRewardsBalance(address[] calldata assets, address user)
external
view
returns (uint256);
/**
* @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards
* @param amount Amount of rewards to claim
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewards(
address[] calldata assets,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must
* be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager
* @param amount Amount of rewards to claim
* @param user Address to check and claim rewards
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewardsOnBehalf(
address[] calldata assets,
uint256 amount,
address user,
address to
) external returns (uint256);
/**
* @dev returns the unclaimed rewards of the user
* @param user the address of the user
* @return the unclaimed user rewards
*/
function getUserUnclaimedRewards(address user) external view returns (uint256);
/**
* @dev for backward compatibility with previous implementation of the Incentives controller
*/
function REWARD_TOKEN() external view returns (address);
struct AssetData {
uint128 emissionPerSecond;
uint128 lastUpdateTimestamp;
uint256 index;
}
function assets(address) external view returns (AssetData memory);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
import {ILendingPoolAddressesProvider} from "./ILendingPoolAddressesProvider.sol";
import {DataTypes} from "../../libraries/aave/DataTypes.sol";
interface ILendingPool {
/**
* @dev Emitted on deposit()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the deposit
* @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
* @param amount The amount deposited
* @param referral The referral code used
**/
event Deposit(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referral
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlyng asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to Address that will receive the underlying
* @param amount The amount to be withdrawn
**/
event Withdraw(
address indexed reserve,
address indexed user,
address indexed to,
uint256 amount
);
/**
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable
* @param borrowRate The numeric rate at which the user has borrowed
* @param referral The referral code used
**/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint256 borrowRateMode,
uint256 borrowRate,
uint16 indexed referral
);
/**
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
**/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount
);
/**
* @dev Emitted on swapBorrowRateMode()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user swapping his rate mode
* @param rateMode The rate mode that the user wants to swap to
**/
event Swap(address indexed reserve, address indexed user, uint256 rateMode);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on rebalanceStableBorrowRate()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user for which the rebalance has been executed
**/
event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
/**
* @dev Emitted on flashLoan()
* @param target The address of the flash loan receiver contract
* @param initiator The address initiating the flash loan
* @param asset The address of the asset being flash borrowed
* @param amount The amount flash borrowed
* @param premium The fee flash borrowed
* @param referralCode The referral code used
**/
event FlashLoan(
address indexed target,
address indexed initiator,
address indexed asset,
uint256 amount,
uint256 premium,
uint16 referralCode
);
/**
* @dev Emitted when the pause is triggered.
*/
event Paused();
/**
* @dev Emitted when the pause is lifted.
*/
event Unpaused();
/**
* @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
* LendingPoolCollateral manager using a DELEGATECALL
* This allows to have the events in the generated ABI for LendingPool.
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param liquidatedCollateralAmount The amount of collateral received by the liiquidator
* @param liquidator The address of the liquidator
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared
* in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
* the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
* gets added to the LendingPool ABI
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The new liquidity rate
* @param stableBorrowRate The new stable borrow rate
* @param variableBorrowRate The new variable borrow rate
* @param liquidityIndex The new liquidity index
* @param variableBorrowIndex The new variable borrow index
**/
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
/**
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User deposits 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to deposit
* @param amount The amount to be deposited
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to Address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
**/
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already deposited enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
**/
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
address onBehalfOf
) external;
/**
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @return The final amount repaid
**/
function repay(
address asset,
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external returns (uint256);
/**
* @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa
* @param asset The address of the underlying asset borrowed
* @param rateMode The rate mode that the user wants to swap to
**/
function swapBorrowRateMode(address asset, uint256 rateMode) external;
/**
* @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
* - Users can be rebalanced if the following conditions are satisfied:
* 1. Usage ratio is above 95%
* 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
* borrowed at a stable rate and depositors are not earning enough
* @param asset The address of the underlying asset borrowed
* @param user The address of the user to be rebalanced
**/
function rebalanceStableBorrowRate(address asset, address user) external;
/**
* @dev Allows depositors to enable/disable a specific deposited asset as collateral
* @param asset The address of the underlying asset deposited
* @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise
**/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover,
bool receiveAToken
) external;
/**
* @dev Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.
* For further details please visit https://developers.aave.com
* @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts amounts being flash-borrowed
* @param modes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function flashLoan(
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata modes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/**
* @dev Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralETH the total collateral in ETH of the user
* @return totalDebtETH the total debt in ETH of the user
* @return availableBorrowsETH the borrowing power left of the user
* @return currentLiquidationThreshold the liquidation threshold of the user
* @return ltv the loan to value of the user
* @return healthFactor the current health factor of the user
**/
function getUserAccountData(address user)
external
view
returns (
uint256 totalCollateralETH,
uint256 totalDebtETH,
uint256 availableBorrowsETH,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
function initReserve(
address reserve,
address aTokenAddress,
address stableDebtAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
external;
function setConfiguration(address reserve, uint256 configuration) external;
/**
* @dev Returns the configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The configuration of the reserve
**/
function getConfiguration(address asset)
external
view
returns (DataTypes.ReserveConfigurationMap memory);
/**
* @dev Returns the configuration of the user across all the reserves
* @param user The user address
* @return The configuration of the user
**/
function getUserConfiguration(address user)
external
view
returns (DataTypes.UserConfigurationMap memory);
/**
* @dev Returns the normalized income normalized income of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset) external view returns (uint256);
/**
* @dev Returns the normalized variable debt per unit of asset
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
/**
* @dev Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state of the reserve
**/
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromAfter,
uint256 balanceToBefore
) external;
function getReservesList() external view returns (address[] memory);
function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);
function setPause(bool val) external;
function paused() external view returns (bool);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
/**
* @title LendingPoolAddressesProvider contract
* @dev Main registry of addresses part of or connected to the protocol, including permissioned roles
* - Acting also as factory of proxies and admin of those, so with right to change its implementations
* - Owned by the Aave Governance
* @author Aave
**/
interface ILendingPoolAddressesProvider {
event MarketIdSet(string newMarketId);
event LendingPoolUpdated(address indexed newAddress);
event ConfigurationAdminUpdated(address indexed newAddress);
event EmergencyAdminUpdated(address indexed newAddress);
event LendingPoolConfiguratorUpdated(address indexed newAddress);
event LendingPoolCollateralManagerUpdated(address indexed newAddress);
event PriceOracleUpdated(address indexed newAddress);
event LendingRateOracleUpdated(address indexed newAddress);
event ProxyCreated(bytes32 id, address indexed newAddress);
event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);
function getMarketId() external view returns (string memory);
function setMarketId(string calldata marketId) external;
function setAddress(bytes32 id, address newAddress) external;
function setAddressAsProxy(bytes32 id, address impl) external;
function getAddress(bytes32 id) external view returns (address);
function getLendingPool() external view returns (address);
function setLendingPoolImpl(address pool) external;
function getLendingPoolConfigurator() external view returns (address);
function setLendingPoolConfiguratorImpl(address configurator) external;
function getLendingPoolCollateralManager() external view returns (address);
function setLendingPoolCollateralManager(address manager) external;
function getPoolAdmin() external view returns (address);
function setPoolAdmin(address admin) external;
function getEmergencyAdmin() external view returns (address);
function setEmergencyAdmin(address admin) external;
function getPriceOracle() external view returns (address);
function setPriceOracle(address priceOracle) external;
function getLendingRateOracle() external view returns (address);
function setLendingRateOracle(address lendingRateOracle) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
/************
@title IPriceOracleGetter interface
@notice Interface for the Aave price oracle.*/
interface IPriceOracleGetter {
/***********
@dev returns the asset price in ETH
*/
function getAssetPrice(address _asset) external view returns (uint256);
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
interface IScaledBalanceToken {
/**
* @dev Returns the scaled balance of the user. The scaled balance is the sum of all the
* updated stored balance divided by the reserve's liquidity index at the moment of the update
* @param user The user whose balance is calculated
* @return The scaled balance of the user
**/
function scaledBalanceOf(address user) external view returns (uint256);
/**
* @dev Returns the scaled balance of the user and the scaled total supply.
* @param user The address of the user
* @return The scaled balance of the user
* @return The scaled balance and the scaled total supply
**/
function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);
/**
* @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index)
* @return The scaled total supply
**/
function scaledTotalSupply() external view returns (uint256);
}// SPDX-License-Identifier: GNU AGPLv3 pragma solidity ^0.8.0; /// @title Types. /// @author Morpho Labs. /// @custom:contact [email protected] /// @dev Common types and structs used in Morpho contracts. library Types { /// ENUMS /// enum PositionType { SUPPLIERS_IN_P2P, SUPPLIERS_ON_POOL, BORROWERS_IN_P2P, BORROWERS_ON_POOL } /// STRUCTS /// struct SupplyBalance { uint256 inP2P; // In supplier's peer-to-peer unit, a unit that grows in underlying value, to keep track of the interests earned by suppliers in peer-to-peer. Multiply by the peer-to-peer supply index to get the underlying amount. uint256 onPool; // In scaled balance. Multiply by the pool supply index to get the underlying amount. } struct BorrowBalance { uint256 inP2P; // In borrower's peer-to-peer unit, a unit that grows in underlying value, to keep track of the interests paid by borrowers in peer-to-peer. Multiply by the peer-to-peer borrow index to get the underlying amount. uint256 onPool; // In adUnit, a unit that grows in value, to keep track of the debt increase when borrowers are on Aave. Multiply by the pool borrow index to get the underlying amount. } // Max gas to consume during the matching process for supply, borrow, withdraw and repay functions. struct MaxGasForMatching { uint64 supply; uint64 borrow; uint64 withdraw; uint64 repay; } struct Delta { uint256 p2pSupplyDelta; // Difference between the stored peer-to-peer supply amount and the real peer-to-peer supply amount (in aToken). uint256 p2pBorrowDelta; // Difference between the stored peer-to-peer borrow amount and the real peer-to-peer borrow amount (in adUnit). uint256 p2pSupplyAmount; // Sum of all stored peer-to-peer supply (in peer-to-peer unit). uint256 p2pBorrowAmount; // Sum of all stored peer-to-peer borrow (in peer-to-peer unit). } struct AssetLiquidityData { uint256 decimals; // The number of decimals of the underlying token. uint256 tokenUnit; // The token unit considering its decimals. uint256 liquidationThreshold; // The liquidation threshold applied on this token (in basis point). uint256 ltv; // The LTV applied on this token (in basis point). uint256 underlyingPrice; // The price of the token (in ETH). uint256 collateral; // The collateral value of the asset (in ETH). uint256 debt; // The debt value of the asset (in ETH). } struct LiquidityData { uint256 collateral; // The collateral value (in ETH). uint256 maxDebt; // The max debt value (in ETH). uint256 liquidationThreshold; // The liquidation threshold value (in ETH). uint256 debt; // The debt value (in ETH). } // Variables are packed together to save gas (will not exceed their limit during Morpho's lifetime). struct PoolIndexes { uint32 lastUpdateTimestamp; // The last time the local pool and peer-to-peer indexes were updated. uint112 poolSupplyIndex; // Last pool supply index. uint112 poolBorrowIndex; // Last pool borrow index. } struct Market { address underlyingToken; // The underlying address of the market. uint16 reserveFactor; // Proportion of the additional interest earned being matched peer-to-peer on Morpho compared to being on the pool. It is sent to the DAO for each market. The default value is 0. In basis point (100% = 10 000). uint16 p2pIndexCursor; // Position of the peer-to-peer rate in the pool's spread. Determine the weights of the weighted arithmetic average in the indexes computations ((1 - p2pIndexCursor) * r^S + p2pIndexCursor * r^B) (in basis point). bool isCreated; // Whether or not this market is created. bool isPaused; // Whether the market is paused or not (all entry points on Morpho are frozen; supply, borrow, withdraw, repay and liquidate). bool isPartiallyPaused; // Whether the market is partially paused or not (only supply and borrow are frozen). bool isP2PDisabled; // Whether the market's peer-to-peer is open or not. } struct LiquidityStackVars { address poolToken; uint256 poolTokensLength; bytes32 userMarkets; bytes32 borrowMask; address underlyingToken; uint256 underlyingPrice; } }
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
library DataTypes {
// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
//tokens addresses
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the id of the reserve. Represents the position in the list of the active reserves
uint8 id;
}
struct ReserveConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: Reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: stable rate borrowing enabled
//bit 60-63: reserved
//bit 64-79: reserve factor
uint256 data;
}
struct UserConfigurationMap {
uint256 data;
}
enum InterestRateMode {
NONE,
STABLE,
VARIABLE
}
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
/**
* @title Errors library
* @author Aave
* @notice Defines the error messages emitted by the different contracts of the Aave protocol
* @dev Error messages prefix glossary:
* - VL = ValidationLogic
* - MATH = Math libraries
* - CT = Common errors between tokens (AToken, VariableDebtToken and StableDebtToken)
* - AT = AToken
* - SDT = StableDebtToken
* - VDT = VariableDebtToken
* - LP = LendingPool
* - LPAPR = LendingPoolAddressesProviderRegistry
* - LPC = LendingPoolConfiguration
* - RL = ReserveLogic
* - LPCM = LendingPoolCollateralManager
* - P = Pausable
*/
library Errors {
//common errors
string public constant CALLER_NOT_POOL_ADMIN = "33"; // 'The caller must be the pool admin'
string public constant BORROW_ALLOWANCE_NOT_ENOUGH = "59"; // User borrows on behalf, but allowance are too small
//contract specific errors
string public constant VL_INVALID_AMOUNT = "1"; // 'Amount must be greater than 0'
string public constant VL_NO_ACTIVE_RESERVE = "2"; // 'Action requires an active reserve'
string public constant VL_RESERVE_FROZEN = "3"; // 'Action cannot be performed because the reserve is frozen'
string public constant VL_CURRENT_AVAILABLE_LIQUIDITY_NOT_ENOUGH = "4"; // 'The current liquidity is not enough'
string public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = "5"; // 'User cannot withdraw more than the available balance'
string public constant VL_TRANSFER_NOT_ALLOWED = "6"; // 'Transfer cannot be allowed.'
string public constant VL_BORROWING_NOT_ENABLED = "7"; // 'Borrowing is not enabled'
string public constant VL_INVALID_INTEREST_RATE_MODE_SELECTED = "8"; // 'Invalid interest rate mode selected'
string public constant VL_COLLATERAL_BALANCE_IS_0 = "9"; // 'The collateral balance is 0'
string public constant VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = "10"; // 'Health factor is lesser than the liquidation threshold'
string public constant VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = "11"; // 'There is not enough collateral to cover a new borrow'
string public constant VL_STABLE_BORROWING_NOT_ENABLED = "12"; // stable borrowing not enabled
string public constant VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY = "13"; // collateral is (mostly) the same currency that is being borrowed
string public constant VL_AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = "14"; // 'The requested amount is greater than the max loan size in stable rate mode
string public constant VL_NO_DEBT_OF_SELECTED_TYPE = "15"; // 'for repayment of stable debt, the user needs to have stable debt, otherwise, he needs to have variable debt'
string public constant VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = "16"; // 'To repay on behalf of an user an explicit amount to repay is needed'
string public constant VL_NO_STABLE_RATE_LOAN_IN_RESERVE = "17"; // 'User does not have a stable rate loan in progress on this reserve'
string public constant VL_NO_VARIABLE_RATE_LOAN_IN_RESERVE = "18"; // 'User does not have a variable rate loan in progress on this reserve'
string public constant VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0 = "19"; // 'The underlying balance needs to be greater than 0'
string public constant VL_DEPOSIT_ALREADY_IN_USE = "20"; // 'User deposit is already being used as collateral'
string public constant LP_NOT_ENOUGH_STABLE_BORROW_BALANCE = "21"; // 'User does not have any stable rate loan for this reserve'
string public constant LP_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = "22"; // 'Interest rate rebalance conditions were not met'
string public constant LP_LIQUIDATION_CALL_FAILED = "23"; // 'Liquidation call failed'
string public constant LP_NOT_ENOUGH_LIQUIDITY_TO_BORROW = "24"; // 'There is not enough liquidity available to borrow'
string public constant LP_REQUESTED_AMOUNT_TOO_SMALL = "25"; // 'The requested amount is too small for a FlashLoan.'
string public constant LP_INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = "26"; // 'The actual balance of the protocol is inconsistent'
string public constant LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = "27"; // 'The caller of the function is not the lending pool configurator'
string public constant LP_INCONSISTENT_FLASHLOAN_PARAMS = "28";
string public constant CT_CALLER_MUST_BE_LENDING_POOL = "29"; // 'The caller of this function must be a lending pool'
string public constant CT_CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = "30"; // 'User cannot give allowance to himself'
string public constant CT_TRANSFER_AMOUNT_NOT_GT_0 = "31"; // 'Transferred amount needs to be greater than zero'
string public constant RL_RESERVE_ALREADY_INITIALIZED = "32"; // 'Reserve has already been initialized'
string public constant LPC_RESERVE_LIQUIDITY_NOT_0 = "34"; // 'The liquidity of the reserve needs to be 0'
string public constant LPC_INVALID_ATOKEN_POOL_ADDRESS = "35"; // 'The liquidity of the reserve needs to be 0'
string public constant LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = "36"; // 'The liquidity of the reserve needs to be 0'
string public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS = "37"; // 'The liquidity of the reserve needs to be 0'
string public constant LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = "38"; // 'The liquidity of the reserve needs to be 0'
string public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = "39"; // 'The liquidity of the reserve needs to be 0'
string public constant LPC_INVALID_ADDRESSES_PROVIDER_ID = "40"; // 'The liquidity of the reserve needs to be 0'
string public constant LPC_INVALID_CONFIGURATION = "75"; // 'Invalid risk parameters for the reserve'
string public constant LPC_CALLER_NOT_EMERGENCY_ADMIN = "76"; // 'The caller must be the emergency admin'
string public constant LPAPR_PROVIDER_NOT_REGISTERED = "41"; // 'Provider is not registered'
string public constant LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = "42"; // 'Health factor is not below the threshold'
string public constant LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = "43"; // 'The collateral chosen cannot be liquidated'
string public constant LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = "44"; // 'User did not borrow the specified currency'
string public constant LPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE = "45"; // "There isn't enough liquidity available to liquidate"
string public constant LPCM_NO_ERRORS = "46"; // 'No errors'
string public constant LP_INVALID_FLASHLOAN_MODE = "47"; //Invalid flashloan mode selected
string public constant MATH_MULTIPLICATION_OVERFLOW = "48";
string public constant MATH_ADDITION_OVERFLOW = "49";
string public constant MATH_DIVISION_BY_ZERO = "50";
string public constant RL_LIQUIDITY_INDEX_OVERFLOW = "51"; // Liquidity index overflows uint128
string public constant RL_VARIABLE_BORROW_INDEX_OVERFLOW = "52"; // Variable borrow index overflows uint128
string public constant RL_LIQUIDITY_RATE_OVERFLOW = "53"; // Liquidity rate overflows uint128
string public constant RL_VARIABLE_BORROW_RATE_OVERFLOW = "54"; // Variable borrow rate overflows uint128
string public constant RL_STABLE_BORROW_RATE_OVERFLOW = "55"; // Stable borrow rate overflows uint128
string public constant CT_INVALID_MINT_AMOUNT = "56"; //invalid amount to mint
string public constant LP_FAILED_REPAY_WITH_COLLATERAL = "57";
string public constant CT_INVALID_BURN_AMOUNT = "58"; //invalid amount to burn
string public constant LP_FAILED_COLLATERAL_SWAP = "60";
string public constant LP_INVALID_EQUAL_ASSETS_TO_SWAP = "61";
string public constant LP_REENTRANCY_NOT_ALLOWED = "62";
string public constant LP_CALLER_MUST_BE_AN_ATOKEN = "63";
string public constant LP_IS_PAUSED = "64"; // 'Pool is paused'
string public constant LP_NO_MORE_RESERVES_ALLOWED = "65";
string public constant LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = "66";
string public constant RC_INVALID_LTV = "67";
string public constant RC_INVALID_LIQ_THRESHOLD = "68";
string public constant RC_INVALID_LIQ_BONUS = "69";
string public constant RC_INVALID_DECIMALS = "70";
string public constant RC_INVALID_RESERVE_FACTOR = "71";
string public constant LPAPR_INVALID_ADDRESSES_PROVIDER_ID = "72";
string public constant VL_INCONSISTENT_FLASHLOAN_PARAMS = "73";
string public constant LP_INCONSISTENT_PARAMS_LENGTH = "74";
string public constant UL_INVALID_INDEX = "77";
string public constant LP_NOT_CONTRACT = "78";
string public constant SDT_STABLE_DEBT_OVERFLOW = "79";
string public constant SDT_BURN_EXCEEDS_BALANCE = "80";
enum CollateralManagerErrors {
NO_ERROR,
NO_COLLATERAL_AVAILABLE,
COLLATERAL_CANNOT_BE_LIQUIDATED,
CURRRENCY_NOT_BORROWED,
HEALTH_FACTOR_ABOVE_THRESHOLD,
NOT_ENOUGH_LIQUIDITY,
NO_ACTIVE_RESERVE,
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
INVALID_EQUAL_ASSETS_TO_SWAP,
FROZEN_RESERVE
}
}// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
import {Errors} from "./Errors.sol";
import {DataTypes} from "./DataTypes.sol";
/**
* @title ReserveConfiguration library
* @author Aave
* @notice Implements the bitmap logic to handle the reserve configuration
*/
library ReserveConfiguration {
uint256 constant LTV_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000; // prettier-ignore
uint256 constant LIQUIDATION_THRESHOLD_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF; // prettier-ignore
uint256 constant LIQUIDATION_BONUS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF; // prettier-ignore
uint256 constant DECIMALS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF; // prettier-ignore
uint256 constant ACTIVE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF; // prettier-ignore
uint256 constant FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; // prettier-ignore
uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore
uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore
uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore
/// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed
uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16;
uint256 constant LIQUIDATION_BONUS_START_BIT_POSITION = 32;
uint256 constant RESERVE_DECIMALS_START_BIT_POSITION = 48;
uint256 constant IS_ACTIVE_START_BIT_POSITION = 56;
uint256 constant IS_FROZEN_START_BIT_POSITION = 57;
uint256 constant BORROWING_ENABLED_START_BIT_POSITION = 58;
uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59;
uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64;
uint256 constant MAX_VALID_LTV = 65535;
uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535;
uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535;
uint256 constant MAX_VALID_DECIMALS = 255;
uint256 constant MAX_VALID_RESERVE_FACTOR = 65535;
/**
* @dev Sets the Loan to Value of the reserve
* @param self The reserve configuration
* @param ltv the new ltv
**/
function setLtv(DataTypes.ReserveConfigurationMap memory self, uint256 ltv) internal pure {
require(ltv <= MAX_VALID_LTV, Errors.RC_INVALID_LTV);
self.data = (self.data & LTV_MASK) | ltv;
}
/**
* @dev Gets the Loan to Value of the reserve
* @param self The reserve configuration
* @return The loan to value
**/
function getLtv(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
{
return self.data & ~LTV_MASK;
}
/**
* @dev Sets the liquidation threshold of the reserve
* @param self The reserve configuration
* @param threshold The new liquidation threshold
**/
function setLiquidationThreshold(
DataTypes.ReserveConfigurationMap memory self,
uint256 threshold
) internal pure {
require(threshold <= MAX_VALID_LIQUIDATION_THRESHOLD, Errors.RC_INVALID_LIQ_THRESHOLD);
self.data =
(self.data & LIQUIDATION_THRESHOLD_MASK) |
(threshold << LIQUIDATION_THRESHOLD_START_BIT_POSITION);
}
/**
* @dev Gets the liquidation threshold of the reserve
* @param self The reserve configuration
* @return The liquidation threshold
**/
function getLiquidationThreshold(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
{
return
(self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION;
}
/**
* @dev Sets the liquidation bonus of the reserve
* @param self The reserve configuration
* @param bonus The new liquidation bonus
**/
function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus)
internal
pure
{
require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.RC_INVALID_LIQ_BONUS);
self.data =
(self.data & LIQUIDATION_BONUS_MASK) |
(bonus << LIQUIDATION_BONUS_START_BIT_POSITION);
}
/**
* @dev Gets the liquidation bonus of the reserve
* @param self The reserve configuration
* @return The liquidation bonus
**/
function getLiquidationBonus(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
{
return (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION;
}
/**
* @dev Sets the decimals of the underlying asset of the reserve
* @param self The reserve configuration
* @param decimals The decimals
**/
function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals)
internal
pure
{
require(decimals <= MAX_VALID_DECIMALS, Errors.RC_INVALID_DECIMALS);
self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION);
}
/**
* @dev Gets the decimals of the underlying asset of the reserve
* @param self The reserve configuration
* @return The decimals of the asset
**/
function getDecimals(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
{
return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION;
}
/**
* @dev Sets the active state of the reserve
* @param self The reserve configuration
* @param active The active state
**/
function setActive(DataTypes.ReserveConfigurationMap memory self, bool active) internal pure {
self.data =
(self.data & ACTIVE_MASK) |
(uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION);
}
/**
* @dev Gets the active state of the reserve
* @param self The reserve configuration
* @return The active state
**/
function getActive(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) {
return (self.data & ~ACTIVE_MASK) != 0;
}
/**
* @dev Sets the frozen state of the reserve
* @param self The reserve configuration
* @param frozen The frozen state
**/
function setFrozen(DataTypes.ReserveConfigurationMap memory self, bool frozen) internal pure {
self.data =
(self.data & FROZEN_MASK) |
(uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION);
}
/**
* @dev Gets the frozen state of the reserve
* @param self The reserve configuration
* @return The frozen state
**/
function getFrozen(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (bool)
{
return (self.data & ~FROZEN_MASK) != 0;
}
/**
* @dev Enables or disables borrowing on the reserve
* @param self The reserve configuration
* @param enabled True if the borrowing needs to be enabled, false otherwise
**/
function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled)
internal
pure
{
self.data =
(self.data & BORROWING_MASK) |
(uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION);
}
/**
* @dev Gets the borrowing state of the reserve
* @param self The reserve configuration
* @return The borrowing state
**/
function getBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self)
internal
pure
returns (bool)
{
return (self.data & ~BORROWING_MASK) != 0;
}
/**
* @dev Enables or disables stable rate borrowing on the reserve
* @param self The reserve configuration
* @param enabled True if the stable rate borrowing needs to be enabled, false otherwise
**/
function setStableRateBorrowingEnabled(
DataTypes.ReserveConfigurationMap memory self,
bool enabled
) internal pure {
self.data =
(self.data & STABLE_BORROWING_MASK) |
(uint256(enabled ? 1 : 0) << STABLE_BORROWING_ENABLED_START_BIT_POSITION);
}
/**
* @dev Gets the stable rate borrowing state of the reserve
* @param self The reserve configuration
* @return The stable rate borrowing state
**/
function getStableRateBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (bool)
{
return (self.data & ~STABLE_BORROWING_MASK) != 0;
}
/**
* @dev Sets the reserve factor of the reserve
* @param self The reserve configuration
* @param reserveFactor The reserve factor
**/
function setReserveFactor(DataTypes.ReserveConfigurationMap memory self, uint256 reserveFactor)
internal
pure
{
require(reserveFactor <= MAX_VALID_RESERVE_FACTOR, Errors.RC_INVALID_RESERVE_FACTOR);
self.data =
(self.data & RESERVE_FACTOR_MASK) |
(reserveFactor << RESERVE_FACTOR_START_BIT_POSITION);
}
/**
* @dev Gets the reserve factor of the reserve
* @param self The reserve configuration
* @return The reserve factor
**/
function getReserveFactor(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
{
return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION;
}
/**
* @dev Gets the configuration flags of the reserve
* @param self The reserve configuration
* @return The state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled
**/
function getFlags(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (
bool,
bool,
bool,
bool
)
{
uint256 dataLocal = self.data;
return (
(dataLocal & ~ACTIVE_MASK) != 0,
(dataLocal & ~FROZEN_MASK) != 0,
(dataLocal & ~BORROWING_MASK) != 0,
(dataLocal & ~STABLE_BORROWING_MASK) != 0
);
}
/**
* @dev Gets the configuration paramters of the reserve
* @param self The reserve configuration
* @return The state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals
**/
function getParams(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256
)
{
uint256 dataLocal = self.data;
return (
dataLocal & ~LTV_MASK,
(dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION,
(dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION,
(dataLocal & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION,
(dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION
);
}
/**
* @dev Gets the configuration paramters of the reserve from a memory object
* @param self The reserve configuration
* @return The state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals
**/
function getParamsMemory(DataTypes.ReserveConfigurationMap memory self)
internal
pure
returns (
uint256,
uint256,
uint256,
uint256,
uint256
)
{
return (
self.data & ~LTV_MASK,
(self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION,
(self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION,
(self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION,
(self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION
);
}
/**
* @dev Gets the configuration flags of the reserve from a memory object
* @param self The reserve configuration
* @return The state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled
**/
function getFlagsMemory(DataTypes.ReserveConfigurationMap memory self)
internal
pure
returns (
bool,
bool,
bool,
bool
)
{
return (
(self.data & ~ACTIVE_MASK) != 0,
(self.data & ~FROZEN_MASK) != 0,
(self.data & ~BORROWING_MASK) != 0,
(self.data & ~STABLE_BORROWING_MASK) != 0
);
}
}// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
library HeapOrdering {
struct Account {
address id; // The address of the account.
uint96 value; // The value of the account.
}
struct HeapArray {
Account[] accounts; // All the accounts.
uint256 size; // The size of the heap portion of the structure, should be less than accounts length, the rest is an unordered array.
mapping(address => uint256) ranks; // A mapping from an address to a rank in accounts. Beware: ranks are shifted by one compared to indexes, so the first rank is 1 and not 0.
}
/// CONSTANTS ///
uint256 private constant ROOT = 1;
/// ERRORS ///
/// @notice Thrown when the address is zero at insertion.
error AddressIsZero();
/// INTERNAL ///
/// @notice Updates an account in the `_heap`.
/// @dev Only call this function when `_id` is in the `_heap` with value `_formerValue` or when `_id` is not in the `_heap` with `_formerValue` equal to 0.
/// @param _heap The heap to modify.
/// @param _id The address of the account to update.
/// @param _formerValue The former value of the account to update.
/// @param _newValue The new value of the account to update.
/// @param _maxSortedUsers The maximum size of the heap.
function update(
HeapArray storage _heap,
address _id,
uint256 _formerValue,
uint256 _newValue,
uint256 _maxSortedUsers
) internal {
uint96 formerValue = SafeCast.toUint96(_formerValue);
uint96 newValue = SafeCast.toUint96(_newValue);
uint256 size = _heap.size;
uint256 newSize = computeSize(size, _maxSortedUsers);
if (size != newSize) _heap.size = newSize;
if (formerValue != newValue) {
if (newValue == 0) remove(_heap, _id, formerValue);
else if (formerValue == 0) insert(_heap, _id, newValue, _maxSortedUsers);
else if (formerValue < newValue) increase(_heap, _id, newValue, _maxSortedUsers);
else decrease(_heap, _id, newValue);
}
}
/// PRIVATE ///
/// @notice Computes a new suitable size from `_size` that is smaller than `_maxSortedUsers`.
/// @dev We use division by 2 to remove the leaves of the heap.
/// @param _size The old size of the heap.
/// @param _maxSortedUsers The maximum size of the heap.
/// @return The new size computed.
function computeSize(uint256 _size, uint256 _maxSortedUsers) private pure returns (uint256) {
while (_size >= _maxSortedUsers) _size >>= 1;
return _size;
}
/// @notice Returns the account of rank `_rank`.
/// @dev The first rank is 1 and the last one is length of the array.
/// @dev Only call this function with positive numbers.
/// @param _heap The heap to search in.
/// @param _rank The rank of the account.
/// @return The account of rank `_rank`.
function getAccount(HeapArray storage _heap, uint256 _rank)
private
view
returns (Account storage)
{
return _heap.accounts[_rank - 1];
}
/// @notice Sets the value at `_rank` in the `_heap` to be `_newValue`.
/// @dev The heap may lose its invariant about the order of the values stored.
/// @dev Only call this function with a rank within array's bounds.
/// @param _heap The heap to modify.
/// @param _rank The rank of the account in the heap to be set.
/// @param _newValue The new value to set the `_rank` to.
function setAccountValue(
HeapArray storage _heap,
uint256 _rank,
uint96 _newValue
) private {
_heap.accounts[_rank - 1].value = _newValue;
}
/// @notice Sets `_rank` in the `_heap` to be `_account`.
/// @dev The heap may lose its invariant about the order of the values stored.
/// @dev Only call this function with a rank within array's bounds.
/// @param _heap The heap to modify.
/// @param _rank The rank of the account in the heap to be set.
/// @param _account The account to set the `_rank` to.
function setAccount(
HeapArray storage _heap,
uint256 _rank,
Account memory _account
) private {
_heap.accounts[_rank - 1] = _account;
_heap.ranks[_account.id] = _rank;
}
/// @notice Swaps two accounts in the `_heap`.
/// @dev The heap may lose its invariant about the order of the values stored.
/// @dev Only call this function with ranks within array's bounds.
/// @param _heap The heap to modify.
/// @param _rank1 The rank of the first account in the heap.
/// @param _rank2 The rank of the second account in the heap.
function swap(
HeapArray storage _heap,
uint256 _rank1,
uint256 _rank2
) private {
if (_rank1 == _rank2) return;
Account memory accountOldRank1 = getAccount(_heap, _rank1);
Account memory accountOldRank2 = getAccount(_heap, _rank2);
setAccount(_heap, _rank1, accountOldRank2);
setAccount(_heap, _rank2, accountOldRank1);
}
/// @notice Moves an account up the heap until its value is smaller than the one of its parent.
/// @dev This functions restores the invariant about the order of the values stored when the account at `_rank` is the only one with value greater than what it should be.
/// @param _heap The heap to modify.
/// @param _rank The rank of the account to move.
function shiftUp(HeapArray storage _heap, uint256 _rank) private {
Account memory accountToShift = getAccount(_heap, _rank);
uint256 valueToShift = accountToShift.value;
Account memory parentAccount;
while (
_rank > ROOT && valueToShift > (parentAccount = getAccount(_heap, _rank >> 1)).value
) {
setAccount(_heap, _rank, parentAccount);
_rank >>= 1;
}
setAccount(_heap, _rank, accountToShift);
}
/// @notice Moves an account down the heap until its value is greater than the ones of its children.
/// @dev This functions restores the invariant about the order of the values stored when the account at `_rank` is the only one with value smaller than what it should be.
/// @param _heap The heap to modify.
/// @param _rank The rank of the account to move.
function shiftDown(HeapArray storage _heap, uint256 _rank) private {
uint256 size = _heap.size;
Account memory accountToShift = getAccount(_heap, _rank);
uint256 valueToShift = accountToShift.value;
uint256 childRank = _rank << 1;
// At this point, childRank (resp. childRank+1) is the rank of the left (resp. right) child.
while (childRank <= size) {
Account memory childToSwap = getAccount(_heap, childRank);
// Find the child with largest value.
if (childRank < size) {
Account memory rightChild = getAccount(_heap, childRank + 1);
if (rightChild.value > childToSwap.value) {
unchecked {
++childRank; // This cannot overflow because childRank < size.
}
childToSwap = rightChild;
}
}
if (childToSwap.value > valueToShift) {
setAccount(_heap, _rank, childToSwap);
_rank = childRank;
childRank <<= 1;
} else break;
}
setAccount(_heap, _rank, accountToShift);
}
/// @notice Inserts an account in the `_heap`.
/// @dev Only call this function when `_id` is not in the `_heap`.
/// @dev Reverts with AddressIsZero if `_value` is 0.
/// @param _heap The heap to modify.
/// @param _id The address of the account to insert.
/// @param _value The value of the account to insert.
/// @param _maxSortedUsers The maximum size of the heap.
function insert(
HeapArray storage _heap,
address _id,
uint96 _value,
uint256 _maxSortedUsers
) private {
// `_heap` cannot contain the 0 address.
if (_id == address(0)) revert AddressIsZero();
// Put the account at the end of accounts.
_heap.accounts.push(Account(_id, _value));
uint256 accountsLength = _heap.accounts.length;
_heap.ranks[_id] = accountsLength;
// Move the account at the end of the heap and restore the invariant.
uint256 newSize = _heap.size + 1;
swap(_heap, newSize, accountsLength);
shiftUp(_heap, newSize);
_heap.size = computeSize(newSize, _maxSortedUsers);
}
/// @notice Decreases the amount of an account in the `_heap`.
/// @dev Only call this function when `_id` is in the `_heap` with a value greater than `_newValue`.
/// @param _heap The heap to modify.
/// @param _id The address of the account to decrease the amount.
/// @param _newValue The new value of the account.
function decrease(
HeapArray storage _heap,
address _id,
uint96 _newValue
) private {
uint256 rank = _heap.ranks[_id];
setAccountValue(_heap, rank, _newValue);
// We only need to restore the invariant if the account is a node in the heap
if (rank <= _heap.size >> 1) shiftDown(_heap, rank);
}
/// @notice Increases the amount of an account in the `_heap`.
/// @dev Only call this function when `_id` is in the `_heap` with a smaller value than `_newValue`.
/// @param _heap The heap to modify.
/// @param _id The address of the account to increase the amount.
/// @param _newValue The new value of the account.
/// @param _maxSortedUsers The maximum size of the heap.
function increase(
HeapArray storage _heap,
address _id,
uint96 _newValue,
uint256 _maxSortedUsers
) private {
uint256 rank = _heap.ranks[_id];
setAccountValue(_heap, rank, _newValue);
uint256 nextSize = _heap.size + 1;
if (rank < nextSize) shiftUp(_heap, rank);
else {
swap(_heap, nextSize, rank);
shiftUp(_heap, nextSize);
_heap.size = computeSize(nextSize, _maxSortedUsers);
}
}
/// @notice Removes an account in the `_heap`.
/// @dev Only call when this function `_id` is in the `_heap` with value `_removedValue`.
/// @param _heap The heap to modify.
/// @param _id The address of the account to remove.
/// @param _removedValue The value of the account to remove.
function remove(
HeapArray storage _heap,
address _id,
uint96 _removedValue
) private {
uint256 rank = _heap.ranks[_id];
uint256 accountsLength = _heap.accounts.length;
// Swap the last account and the account to remove, then pop it.
swap(_heap, rank, accountsLength);
if (_heap.size == accountsLength) _heap.size--;
_heap.accounts.pop();
delete _heap.ranks[_id];
// If the swapped account is in the heap, restore the invariant: its value can be smaller or larger than the removed value.
if (rank <= _heap.size) {
if (_removedValue > getAccount(_heap, rank).value) shiftDown(_heap, rank);
else shiftUp(_heap, rank);
}
}
/// GETTERS ///
/// @notice Returns the number of users in the `_heap`.
/// @param _heap The heap parameter.
/// @return The length of the heap.
function length(HeapArray storage _heap) internal view returns (uint256) {
return _heap.accounts.length;
}
/// @notice Returns the value of the account linked to `_id`.
/// @param _heap The heap to search in.
/// @param _id The address of the account.
/// @return The value of the account.
function getValueOf(HeapArray storage _heap, address _id) internal view returns (uint256) {
uint256 rank = _heap.ranks[_id];
if (rank == 0) return 0;
else return getAccount(_heap, rank).value;
}
/// @notice Returns the address at the head of the `_heap`.
/// @param _heap The heap to get the head.
/// @return The address of the head.
function getHead(HeapArray storage _heap) internal view returns (address) {
if (_heap.accounts.length > 0) return getAccount(_heap, ROOT).id;
else return address(0);
}
/// @notice Returns the address at the tail of unsorted portion of the `_heap`.
/// @param _heap The heap to get the tail.
/// @return The address of the tail.
function getTail(HeapArray storage _heap) internal view returns (address) {
if (_heap.accounts.length > 0) return getAccount(_heap, _heap.accounts.length).id;
else return address(0);
}
/// @notice Returns the address coming before `_id` in accounts.
/// @dev The account associated to the returned address does not necessarily have a lower value than the one of the account associated to `_id`.
/// @param _heap The heap to search in.
/// @param _id The address of the account.
/// @return The address of the previous account.
function getPrev(HeapArray storage _heap, address _id) internal view returns (address) {
uint256 rank = _heap.ranks[_id];
if (rank > ROOT) return getAccount(_heap, rank - 1).id;
else return address(0);
}
/// @notice Returns the address coming after `_id` in accounts.
/// @dev The account associated to the returned address does not necessarily have a greater value than the one of the account associated to `_id`.
/// @param _heap The heap to search in.
/// @param _id The address of the account.
/// @return The address of the next account.
function getNext(HeapArray storage _heap, address _id) internal view returns (address) {
uint256 rank = _heap.ranks[_id];
if (rank < _heap.accounts.length) return getAccount(_heap, rank + 1).id;
else return address(0);
}
}// SPDX-License-Identifier: GNU AGPLv3 pragma solidity ^0.8.0; /// @title Delegate Call Library. /// @author Morpho Labs. /// @custom:contact [email protected] /// @dev Low-level YUL delegate call library. library DelegateCall { /// ERRORS /// /// @notice Thrown when a low delegate call has failed without error message. error LowLevelDelegateCallFailed(); bytes4 constant LowLevelDelegateCallFailedError = 0x06f7035e; // bytes4(keccak256("LowLevelDelegateCallFailed()")) /// INTERNAL /// /// @dev Performs a low-level delegate call to the `_target` contract. /// @dev Note: Unlike the OZ's library this function does not check if the `_target` is a contract. It is the responsibility of the caller to ensure that the `_target` is a contract. /// @param _target The address of the target contract. /// @param _data The data to pass to the function called on the target contract. /// @return returnData The return data from the function called on the target contract. function functionDelegateCall(address _target, bytes memory _data) internal returns (bytes memory returnData) { assembly { returnData := mload(0x40) // The bytes size is found at the bytes pointer memory address - the bytes data is found a slot further. if iszero(delegatecall(gas(), _target, add(_data, 0x20), mload(_data), 0, 0)) { // No error is returned, return the custom error. if iszero(returndatasize()) { mstore(returnData, LowLevelDelegateCallFailedError) revert(returnData, 4) } // An error is returned and can be logged. returndatacopy(returnData, 0, returndatasize()) revert(returnData, returndatasize()) } // Copy data size and then the returned data to memory. mstore(returnData, returndatasize()) let actualDataPtr := add(returnData, 0x20) returndatacopy(actualDataPtr, 0, returndatasize()) // Update the free memory pointer. mstore(0x40, add(actualDataPtr, returndatasize())) } } }
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.0;
library Math {
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := add(mul(x, lt(x, y)), mul(y, iszero(lt(x, y))))
}
}
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := add(mul(x, gt(x, y)), mul(y, iszero(gt(x, y))))
}
}
/// @dev Returns max(x - y, 0).
function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := mul(gt(x, y), sub(x, y))
}
}
/// @dev Returns x / y rounded up (x / y + boolAsInt(x % y > 0)).
function divUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
// Revert if y = 0
if iszero(y) {
revert(0, 0)
}
z := add(gt(mod(x, y), 0), div(x, y))
}
}
}// SPDX-License-Identifier: GNU AGPLv3 pragma solidity ^0.8.0; /// @title PercentageMath. /// @author Morpho Labs. /// @custom:contact [email protected] /// @notice Optimized version of Aave V3 math library PercentageMath to conduct percentage manipulations: https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/libraries/math/PercentageMath.sol library PercentageMath { /// CONSTANTS /// uint256 internal constant PERCENTAGE_FACTOR = 1e4; uint256 internal constant HALF_PERCENTAGE_FACTOR = 0.5e4; uint256 internal constant MAX_UINT256 = 2**256 - 1; uint256 internal constant MAX_UINT256_MINUS_HALF_PERCENTAGE = 2**256 - 1 - 0.5e4; /// ERRORS /// // Thrown when percentage is above 100%. error PercentageTooHigh(); /// INTERNAL /// /// @notice Executes a percentage multiplication. /// @param x The value of which the percentage needs to be calculated. /// @param percentage The percentage of the value to be calculated. /// @return y The result of the multiplication. function percentMul(uint256 x, uint256 percentage) internal pure returns (uint256 y) { // Let percentage > 0 // Overflow if x * percentage + HALF_PERCENTAGE_FACTOR > type(uint256).max // <=> x * percentage > type(uint256).max - HALF_PERCENTAGE_FACTOR // <=> x > (type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage assembly { if mul(percentage, gt(x, div(MAX_UINT256_MINUS_HALF_PERCENTAGE, percentage))) { revert(0, 0) } y := div(add(mul(x, percentage), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR) } } /// @notice Executes a percentage division. /// @param x The value of which the percentage needs to be calculated. /// @param percentage The percentage of the value to be calculated. /// @return y The result of the division. function percentDiv(uint256 x, uint256 percentage) internal pure returns (uint256 y) { // let percentage > 0 // Overflow if x * PERCENTAGE_FACTOR + halfPercentage > type(uint256).max // <=> x * PERCENTAGE_FACTOR > type(uint256).max - halfPercentage // <=> x > type(uint256).max - halfPercentage / PERCENTAGE_FACTOR assembly { y := div(percentage, 2) if iszero(mul(percentage, iszero(gt(x, div(sub(MAX_UINT256, y), PERCENTAGE_FACTOR))))) { revert(0, 0) } y := div(add(mul(x, PERCENTAGE_FACTOR), y), percentage) } } /// @notice Executes a weighted average, given an interval [x, y] and a percent p: x * (1 - p) + y * p /// @param x The value at the start of the interval (included). /// @param y The value at the end of the interval (included). /// @param percentage The percentage of the interval to be calculated. /// @return the average of x and y, weighted by percentage. function weightedAvg( uint256 x, uint256 y, uint256 percentage ) internal pure returns (uint256) { if (percentage > PERCENTAGE_FACTOR) revert PercentageTooHigh(); return percentMul(x, PERCENTAGE_FACTOR - percentage) + percentMul(y, percentage); } }
// SPDX-License-Identifier: GNU AGPLv3 pragma solidity ^0.8.0; /// @title WadRayMath. /// @author Morpho Labs. /// @custom:contact [email protected] /// @notice Optimized version of Aave V3 math library WadRayMath to conduct wad and ray manipulations: https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/libraries/math/WadRayMath.sol library WadRayMath { /// CONSTANTS /// uint256 internal constant WAD = 1e18; uint256 internal constant HALF_WAD = 0.5e18; uint256 internal constant RAY = 1e27; uint256 internal constant HALF_RAY = 0.5e27; uint256 internal constant WAD_RAY_RATIO = 1e9; uint256 internal constant HALF_WAD_RAY_RATIO = 0.5e9; uint256 internal constant MAX_UINT256 = 2**256 - 1; // Not possible to use type(uint256).max in yul. uint256 internal constant MAX_UINT256_MINUS_HALF_WAD = 2**256 - 1 - 0.5e18; uint256 internal constant MAX_UINT256_MINUS_HALF_RAY = 2**256 - 1 - 0.5e27; /// INTERNAL /// /// @dev Multiplies two wad, rounding half up to the nearest wad. /// @param x Wad. /// @param y Wad. /// @return z The result of x * y, in wad. function wadMul(uint256 x, uint256 y) internal pure returns (uint256 z) { // Let y > 0 // Overflow if (x * y + HALF_WAD) > type(uint256).max // <=> x * y > type(uint256).max - HALF_WAD // <=> x > (type(uint256).max - HALF_WAD) / y assembly { if mul(y, gt(x, div(MAX_UINT256_MINUS_HALF_WAD, y))) { revert(0, 0) } z := div(add(mul(x, y), HALF_WAD), WAD) } } /// @dev Divides two wad, rounding half up to the nearest wad. /// @param x Wad. /// @param y Wad. /// @return z The result of x / y, in wad. function wadDiv(uint256 x, uint256 y) internal pure returns (uint256 z) { // Overflow if y == 0 // Overflow if (x * WAD + y / 2) > type(uint256).max // <=> x * WAD > type(uint256).max - y / 2 // <=> x > (type(uint256).max - y / 2) / WAD assembly { z := div(y, 2) if iszero(mul(y, iszero(gt(x, div(sub(MAX_UINT256, z), WAD))))) { revert(0, 0) } z := div(add(mul(x, WAD), z), y) } } /// @dev Multiplies two ray, rounding half up to the nearest ray. /// @param x Ray. /// @param y Ray. /// @return z The result of x * y, in ray. function rayMul(uint256 x, uint256 y) internal pure returns (uint256 z) { // Let y > 0 // Overflow if (x * y + HALF_RAY) > type(uint256).max // <=> x * y > type(uint256).max - HALF_RAY // <=> x > (type(uint256).max - HALF_RAY) / y assembly { if mul(y, gt(x, div(MAX_UINT256_MINUS_HALF_RAY, y))) { revert(0, 0) } z := div(add(mul(x, y), HALF_RAY), RAY) } } /// @dev Divides two ray, rounding half up to the nearest ray. /// @param x Ray. /// @param y Ray. /// @return z The result of x / y, in ray. function rayDiv(uint256 x, uint256 y) internal pure returns (uint256 z) { // Overflow if y == 0 // Overflow if (x * RAY + y / 2) > type(uint256).max // <=> x * RAY > type(uint256).max - y / 2 // <=> x > (type(uint256).max - y / 2) / RAY assembly { z := div(y, 2) if iszero(mul(y, iszero(gt(x, div(sub(MAX_UINT256, z), RAY))))) { revert(0, 0) } z := div(add(mul(x, RAY), z), y) } } /// @dev Casts ray down to wad. /// @param x Ray. /// @return y = x converted to wad, rounded half up to the nearest wad. function rayToWad(uint256 x) internal pure returns (uint256 y) { assembly { // If x % WAD_RAY_RATIO >= HALF_WAD_RAY_RATIO, round up. y := add(div(x, WAD_RAY_RATIO), iszero(lt(mod(x, WAD_RAY_RATIO), HALF_WAD_RAY_RATIO))) } } /// @dev Converts wad up to ray. /// @param x Wad. /// @return y = x converted in ray. function wadToRay(uint256 x) internal pure returns (uint256 y) { assembly { y := mul(x, WAD_RAY_RATIO) // Revert if y / WAD_RAY_RATIO != x if iszero(eq(div(y, WAD_RAY_RATIO), x)) { revert(0, 0) } } } }
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @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[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @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[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @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[50] private __gap;
}{
"remappings": [
"@aave/core-v3/=lib/aave-v3-core/",
"@aave/periphery-v3/=lib/aave-v3-periphery/",
"@contracts/=contracts/",
"@forge-std/=lib/forge-std/src/",
"@morpho-dao/morpho-data-structures/=lib/morpho-data-structures/contracts/",
"@morpho-dao/morpho-utils/=lib/morpho-utils/src/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@rari-capital/solmate/=lib/solmate/",
"aave-v3-core/=lib/aave-v3-core/",
"aave-v3-periphery/=lib/aave-v3-periphery/contracts/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"hardhat/=node_modules/hardhat/",
"morpho-utils/=lib/morpho-utils/src/",
"openzeppelin-contracts/=lib/morpho-utils/lib/openzeppelin-contracts/",
"solmate/=lib/solmate/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"debug": {
"revertStrings": "default"
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ClaimRewardsPaused","type":"error"},{"inputs":[],"name":"ExceedsMaxBasisPoints","type":"error"},{"inputs":[],"name":"MarketAlreadyCreated","type":"error"},{"inputs":[],"name":"MarketIsNotListedOnAave","type":"error"},{"inputs":[],"name":"MarketNotCreated","type":"error"},{"inputs":[],"name":"MarketPaused","type":"error"},{"inputs":[],"name":"MaxNumberOfMarkets","type":"error"},{"inputs":[],"name":"MaxSortedUsersCannotBeZero","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_aaveIncentivesController","type":"address"}],"name":"AaveIncentivesControllerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"ClaimRewardsPauseStatusSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint64","name":"supply","type":"uint64"},{"internalType":"uint64","name":"borrow","type":"uint64"},{"internalType":"uint64","name":"withdraw","type":"uint64"},{"internalType":"uint64","name":"repay","type":"uint64"}],"indexed":false,"internalType":"struct Types.MaxGasForMatching","name":"_defaultMaxGasForMatching","type":"tuple"}],"name":"DefaultMaxGasForMatchingSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_entryPositionsManager","type":"address"}],"name":"EntryPositionsManagerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_exitPositionsManager","type":"address"}],"name":"ExitPositionsManagerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_newIncentivesVaultAddress","type":"address"}],"name":"IncentivesVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_interestRatesManager","type":"address"}],"name":"InterestRatesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_poolToken","type":"address"},{"indexed":false,"internalType":"uint16","name":"_reserveFactor","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"_p2pIndexCursor","type":"uint16"}],"name":"MarketCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_newValue","type":"uint256"}],"name":"MaxSortedUsersSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_poolToken","type":"address"},{"indexed":false,"internalType":"uint16","name":"_newValue","type":"uint16"}],"name":"P2PIndexCursorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_poolToken","type":"address"},{"indexed":false,"internalType":"bool","name":"_isP2PDisabled","type":"bool"}],"name":"P2PStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_poolToken","type":"address"},{"indexed":false,"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"PartialPauseStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_poolToken","type":"address"},{"indexed":false,"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"PauseStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_poolToken","type":"address"},{"indexed":false,"internalType":"uint16","name":"_newValue","type":"uint16"}],"name":"ReserveFactorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_poolToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amountClaimed","type":"uint256"}],"name":"ReserveFeeClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_user","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amountClaimed","type":"uint256"},{"indexed":true,"internalType":"bool","name":"_traded","type":"bool"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_newRewardsManagerAddress","type":"address"}],"name":"RewardsManagerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_newTreasuryVaultAddress","type":"address"}],"name":"TreasuryVaultSet","type":"event"},{"inputs":[],"name":"BORROWING_MASK","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_LIQUIDATION_CLOSE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HEALTH_FACTOR_LIQUIDATION_THRESHOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BASIS_POINTS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_NB_OF_MARKETS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NO_REFERRAL_CODE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VARIABLE_INTEREST_MODE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"aaveIncentivesController","outputs":[{"internalType":"contract IAaveIncentivesController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"addressesProvider","outputs":[{"internalType":"contract ILendingPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxGasForMatching","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"borrowBalanceInOf","outputs":[{"internalType":"uint256","name":"inP2P","type":"uint256"},{"internalType":"uint256","name":"onPool","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"borrowMask","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"bool","name":"_tradeForMorphoToken","type":"bool"}],"name":"claimRewards","outputs":[{"internalType":"uint256","name":"claimedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_poolTokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"claimToTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_underlyingToken","type":"address"},{"internalType":"uint16","name":"_reserveFactor","type":"uint16"},{"internalType":"uint16","name":"_p2pIndexCursor","type":"uint16"}],"name":"createMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultMaxGasForMatching","outputs":[{"internalType":"uint64","name":"supply","type":"uint64"},{"internalType":"uint64","name":"borrow","type":"uint64"},{"internalType":"uint64","name":"withdraw","type":"uint64"},{"internalType":"uint64","name":"repay","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deltas","outputs":[{"internalType":"uint256","name":"p2pSupplyDelta","type":"uint256"},{"internalType":"uint256","name":"p2pBorrowDelta","type":"uint256"},{"internalType":"uint256","name":"p2pSupplyAmount","type":"uint256"},{"internalType":"uint256","name":"p2pBorrowAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"entryPositionsManager","outputs":[{"internalType":"contract IEntryPositionsManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exitPositionsManager","outputs":[{"internalType":"contract IExitPositionsManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"enum Types.PositionType","name":"_positionType","type":"uint8"}],"name":"getHead","outputs":[{"internalType":"address","name":"head","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMarketsCreated","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"enum Types.PositionType","name":"_positionType","type":"uint8"},{"internalType":"address","name":"_user","type":"address"}],"name":"getNext","outputs":[{"internalType":"address","name":"next","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incentivesVault","outputs":[{"internalType":"contract IIncentivesVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"increaseP2PDeltas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IEntryPositionsManager","name":"_entryPositionsManager","type":"address"},{"internalType":"contract IExitPositionsManager","name":"_exitPositionsManager","type":"address"},{"internalType":"contract IInterestRatesManager","name":"_interestRatesManager","type":"address"},{"internalType":"contract ILendingPoolAddressesProvider","name":"_lendingPoolAddressesProvider","type":"address"},{"components":[{"internalType":"uint64","name":"supply","type":"uint64"},{"internalType":"uint64","name":"borrow","type":"uint64"},{"internalType":"uint64","name":"withdraw","type":"uint64"},{"internalType":"uint64","name":"repay","type":"uint64"}],"internalType":"struct Types.MaxGasForMatching","name":"_defaultMaxGasForMatching","type":"tuple"},{"internalType":"uint256","name":"_maxSortedUsers","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"interestRatesManager","outputs":[{"internalType":"contract IInterestRatesManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isClaimRewardsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolTokenBorrowed","type":"address"},{"internalType":"address","name":"_poolTokenCollateral","type":"address"},{"internalType":"address","name":"_borrower","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"market","outputs":[{"internalType":"address","name":"underlyingToken","type":"address"},{"internalType":"uint16","name":"reserveFactor","type":"uint16"},{"internalType":"uint16","name":"p2pIndexCursor","type":"uint16"},{"internalType":"bool","name":"isCreated","type":"bool"},{"internalType":"bool","name":"isPaused","type":"bool"},{"internalType":"bool","name":"isPartiallyPaused","type":"bool"},{"internalType":"bool","name":"isP2PDisabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSortedUsers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"p2pBorrowIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"p2pSupplyIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract ILendingPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolIndexes","outputs":[{"internalType":"uint32","name":"lastUpdateTimestamp","type":"uint32"},{"internalType":"uint112","name":"poolSupplyIndex","type":"uint112"},{"internalType":"uint112","name":"poolBorrowIndex","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"address","name":"_onBehalf","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardsManager","outputs":[{"internalType":"contract IRewardsManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_aaveIncentivesController","type":"address"}],"name":"setAaveIncentivesController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"setAssetAsCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"setClaimRewardsPauseStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"supply","type":"uint64"},{"internalType":"uint64","name":"borrow","type":"uint64"},{"internalType":"uint64","name":"withdraw","type":"uint64"},{"internalType":"uint64","name":"repay","type":"uint64"}],"internalType":"struct Types.MaxGasForMatching","name":"_defaultMaxGasForMatching","type":"tuple"}],"name":"setDefaultMaxGasForMatching","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IEntryPositionsManager","name":"_entryPositionsManager","type":"address"}],"name":"setEntryPositionsManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IExitPositionsManager","name":"_exitPositionsManager","type":"address"}],"name":"setExitPositionsManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IIncentivesVault","name":"_incentivesVault","type":"address"}],"name":"setIncentivesVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IInterestRatesManager","name":"_interestRatesManager","type":"address"}],"name":"setInterestRatesManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMaxSortedUsers","type":"uint256"}],"name":"setMaxSortedUsers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"setP2PDisabledStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint16","name":"_p2pIndexCursor","type":"uint16"}],"name":"setP2PIndexCursor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"setPartialPauseStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"setPauseStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_newStatus","type":"bool"}],"name":"setPauseStatusForAllMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint16","name":"_newReserveFactor","type":"uint16"}],"name":"setReserveFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRewardsManager","name":"_rewardsManager","type":"address"}],"name":"setRewardsManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasuryVault","type":"address"}],"name":"setTreasuryVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"address","name":"_onBehalf","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"address","name":"_onBehalf","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxGasForMatching","type":"uint256"}],"name":"supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"supplyBalanceInOf","outputs":[{"internalType":"uint256","name":"inP2P","type":"uint256"},{"internalType":"uint256","name":"onPool","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"}],"name":"updateIndexes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userMarkets","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b50600054610100900460ff166200002f5760005460ff161562000039565b62000039620000de565b620000a15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000c4576000805461ffff19166101011790555b8015620000d7576000805461ff00191690555b506200010b565b6000620000f630620000fc60201b620034501760201c565b15905090565b6001600160a01b03163b151590565b61430e806200011b6000396000f3fe608060405234801561001057600080fd5b50600436106103fc5760003560e01c8063947574ac11610215578063caf642f911610125578063e61c6d6f116100b8578063f3fef3a311610087578063f3fef3a314610ae3578063f4ea93d814610af6578063f62256c714610b12578063f8180c6614610b25578063fb8b758d14610b3857600080fd5b8063e61c6d6f14610a4f578063f2b9fdb814610a58578063f2f4ca1614610a6b578063f2fde38b14610ad057600080fd5b8063defe2053116100f4578063defe2053146109e4578063df303f8a146109f7578063e501ed0414610a0a578063e5a602ac14610a3c57600080fd5b8063caf642f914610998578063cb830d03146109ab578063d5f80c34146109c8578063d664f72c146109db57600080fd5b8063b24be687116101a8578063c1bce0b711610177578063c1bce0b714610948578063c2ee3a081461095b578063c3525c2814610963578063c72c4d1014610972578063c7a5b9831461098557600080fd5b8063b24be687146108db578063b505e7a2146108ee578063b650f86d14610915578063bc45d1901461092857600080fd5b8063a1d6000c116101e4578063a1d6000c1461088d578063a2253eec146108a2578063aab3f868146108b5578063af8b1c6f146108c857600080fd5b8063947574ac146107315780639f382f6a14610778578063a086fc2214610830578063a10c02501461088557600080fd5b806341bb0725116103105780636ade4661116102a35780637f3ad056116102725780637f3ad056146106c757806380a67a7d146106da578063854f7ebb146106ed5780638da5cb5b1461070d5780639023951b1461071e57600080fd5b80636ade466114610686578063715018a6146106995780637683a908146106a1578063789caa3e146106b457600080fd5b80635f2475ca116102df5780635f2475ca146105de57806361749c98146105f1578063661cd5fc1461060457806369328dec1461067357600080fd5b806341bb0725146105925780634b8a3529146105a5578063582d44bb146105b85780635acff027146105cb57600080fd5b80632ebf4be011610393578063381adc6b11610362578063381adc6b146105265780633b0a79ec146105465780633c42c3b7146105595780633cfe57381461056c578063411302501461057f57600080fd5b80632ebf4be0146104c65780632ff34fe1146104e657806331bc9959146104f9578063361399f41461051357600080fd5b806316f0115b116103cf57806316f0115b146104625780631da649cf1461048d5780631f3d2e6e146104a057806322867d78146104b357600080fd5b80630a8ddc5e146104015780630c0a769b146104165780630cda22dc14610429578063148e23ce1461043c575b600080fd5b61041461040f36600461390a565b610b40565b005b610414610424366004613927565b610bbd565b61041461043736600461390a565b610ced565b61044f61044a3660046139c3565b610d88565b6040519081526020015b60405180910390f35b60aa54610475906001600160a01b031681565b6040516001600160a01b039091168152602001610459565b61041461049b366004613927565b611008565b6104146104ae366004613a16565b611127565b6104146104c1366004613a31565b6111f6565b61044f6104d436600461390a565b60a36020526000908152604090205481565b6104146104f4366004613a5d565b611320565b610501600081565b60405160ff9091168152602001610459565b610414610521366004613a76565b6113a7565b61044f61053436600461390a565b60a76020526000908152604090205481565b60ac54610475906001600160a01b031681565b61041461056736600461390a565b611491565b61041461057a36600461390a565b61152c565b61041461058d36600461390a565b6115a0565b6104146105a0366004613a76565b61163b565b6104146105b3366004613a31565b611717565b6104146105c6366004613a76565b611840565b6104756105d9366004613aba565b61190f565b60a954610475906001600160a01b031681565b6104146105ff366004613af8565b6119ef565b61064761061236600461390a565b60a46020526000908152604090205463ffffffff8116906001600160701b036401000000008204811691600160901b90041683565b6040805163ffffffff90941684526001600160701b039283166020850152911690820152606001610459565b610414610681366004613b34565b611fe0565b610414610694366004613c51565b6120ff565b610414612328565b6104146106af366004613cc9565b61235e565b6104756106c2366004613ce5565b612459565b60ad54610475906001600160a01b031681565b6104146106e8366004613a16565b61253e565b61044f6106fb36600461390a565b60a26020526000908152604090205481565b6033546001600160a01b0316610475565b61041461072c366004613d23565b6125a9565b61076361073f366004613d8e565b609f6020908152600092835260408084209091529082529020805460019091015482565b60408051928352602083019190915201610459565b6107e361078636600461390a565b60a5602052600090815260409020546001600160a01b0381169061ffff600160a01b8204811691600160b01b81049091169060ff600160c01b8204811691600160c81b8104821691600160d01b8204811691600160d81b90041687565b604080516001600160a01b03909816885261ffff9687166020890152959094169486019490945290151560608501521515608084015290151560a0830152151560c082015260e001610459565b61086561083e36600461390a565b60a66020526000908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610459565b610501600281565b610895612815565b6040516104599190613dc7565b6104146108b036600461390a565b612877565b6104146108c3366004613e14565b6128c6565b60b054610475906001600160a01b031681565b60ae54610475906001600160a01b031681565b61044f7f555555555555555555555555555555555555555555555555555555555555555581565b61041461092336600461390a565b612b27565b61044f61093636600461390a565b60a06020526000908152604090205481565b610414610956366004613e65565b612b9b565b61044f600181565b61044f670de0b6b3a764000081565b60a854610475906001600160a01b031681565b610414610993366004613a76565b612caf565b6104146109a6366004613a31565b612d7e565b6097546109b89060ff1681565b6040519015158152602001610459565b6104146109d636600461390a565b612dd6565b61044f61138881565b60af54610475906001600160a01b031681565b610414610a05366004613e9a565b612e4a565b610763610a18366004613d8e565b609e6020908152600092835260408084209091529082529020805460019091015482565b610414610a4a366004613e9a565b612f4d565b61044f60985481565b610414610a66366004613a31565b613050565b609954610a9d906001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b0395861681529385166020850152918416918301919091529091166060820152608001610459565b610414610ade36600461390a565b613174565b610414610af1366004613a31565b61320f565b610aff61271081565b60405161ffff9091168152602001610459565b610414610b20366004613ec6565b61332e565b60ab54610475906001600160a01b031681565b61044f608081565b6033546001600160a01b03163314610b735760405162461bcd60e51b8152600401610b6a90613f0c565b60405180910390fd5b60af80546001600160a01b0319166001600160a01b0383169081179091556040517f22597c132d394cddf8eee9722c4dfc456da51de4c9d9cdf2b8f2523ae0e7eb8190600090a250565b600260655403610bdf5760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808416600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c08201528491610c97576040516396e1352960e01b815260040160405180910390fd5b806080015180610ca857508060a001515b15610cc657604051630a9105a360e31b815260040160405180910390fd5b609954610ce1908690869086906001600160401b031661345f565b50506001606555505050565b6033546001600160a01b03163314610d175760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038116610d3e5760405163d92e233d60e01b815260040160405180910390fd5b60ab80546001600160a01b0319166001600160a01b0383169081179091556040517f7c0388b4f238710366ef8639dfdbad78e473a2b381ddde99fdcb50de646bf51090600090a250565b6000600260655403610dac5760405162461bcd60e51b8152600401610b6a90613f41565b600260655560975460ff1615610dd557604051633be92ecd60e21b815260040160405180910390fd5b60af5460a954604051632b70a16560e11b81526001600160a01b03928316926356e142ca92610e0f92911690889088903390600401613fc1565b6020604051808303816000875af1158015610e2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e529190613ff8565b90508015610ffc578115610f475760a95460ae54604051633111e7b360e01b81526001600160a01b0392831692633111e7b392610e9a92899289928892911690600401614011565b6020604051808303816000875af1158015610eb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edd9190613ff8565b5060ae546040516308c487b560e41b8152336004820152602481018390526001600160a01b0390911690638c487b5090604401600060405180830381600087803b158015610f2a57600080fd5b505af1158015610f3e573d6000803e3d6000fd5b50505050610fc2565b60a954604051633111e7b360e01b81526001600160a01b0390911690633111e7b390610f7d908790879086903390600401614011565b6020604051808303816000875af1158015610f9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc09190613ff8565b505b6040518181528215159033907fab3c4ae116d5285676cffaad9c32cae8acf49b49ca0fc9953b029f97acb955ef9060200160405180910390a35b60016065559392505050565b60026065540361102a5760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808416600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015284916110e2576040516396e1352960e01b815260040160405180910390fd5b80608001511561110557604051630a9105a360e31b815260040160405180910390fd5b609954610ce190869086908690600160c01b90046001600160401b03166134e9565b6033546001600160a01b031633146111515760405162461bcd60e51b8152600401610b6a90613f0c565b60a15460005b818110156111f157600060a1828154811061117457611174614046565b6000918252602080832091909101546001600160a01b031680835260a58252604092839020805460ff60c81b1916600160c81b891515908102919091179091559251928352925082917f5fb0304a827d06fca0ab552393a60b0224e0ac91b574df99de28e8f8bf891605910160405180910390a250600101611157565b505050565b6002606554036112185760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808316600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015283916112d0576040516396e1352960e01b815260040160405180910390fd5b8060800151156112f357604051630a9105a360e31b815260040160405180910390fd5b60995461131590859033908690600160c01b90046001600160401b03166134e9565b505060016065555050565b6033546001600160a01b0316331461134a5760405162461bcd60e51b8152600401610b6a90613f0c565b8060000361136b5760405163275644a160e21b815260040160405180910390fd5b60988190556040518181527f51f9468910070fc9ae906e375f46182f4f84ab311131794a3eceb0b6b80e7f1b906020015b60405180910390a150565b6033546001600160a01b031633146113d15760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff16611413576040516396e1352960e01b815260040160405180910390fd5b60aa546001600160a01b03848116600090815260a5602052604090819020549051635a3b74b960e01b815290821660048201528415156024820152911690635a3b74b990604401600060405180830381600087803b15801561147457600080fd5b505af1158015611488573d6000803e3d6000fd5b50505050505050565b6033546001600160a01b031633146114bb5760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b0381166114e25760405163d92e233d60e01b815260040160405180910390fd5b60ac80546001600160a01b0319166001600160a01b0383169081179091556040517f3dcc0a66d404037e318c6af57572c7f3dfe9250a0a58df79167e76795027946d90600090a250565b6033546001600160a01b031633146115565760405162461bcd60e51b8152600401610b6a90613f0c565b60a980546001600160a01b0319166001600160a01b0383169081179091556040517f9f43a60bcf56fe19c6ef946464526881d6871673d5b8e62fb4df922882abcb4990600090a250565b6033546001600160a01b031633146115ca5760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b0381166115f15760405163d92e233d60e01b815260040160405180910390fd5b60ad80546001600160a01b0319166001600160a01b0383169081179091556040517fc1a4bb1bd557bbfbac2d5702ef3fd93590f2c98c8ccc7f4200564e5992a2aaa590600090a250565b6033546001600160a01b031633146116655760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff166116a7576040516396e1352960e01b815260040160405180910390fd5b6001600160a01b038316600081815260a56020526040908190208054851515600160d01b0260ff60d01b19909116179055517f5024f94e1f582131506b852f4d0aaaaf1c4f03825397c5e64da730ada4e2437a9061170a90851515815260200190565b60405180910390a2505050565b6002606554036117395760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808316600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015283916117f1576040516396e1352960e01b815260040160405180910390fd5b80608001518061180257508060a001515b1561182057604051630a9105a360e31b815260040160405180910390fd5b6099546113159085908590600160401b90046001600160401b031661352c565b6033546001600160a01b0316331461186a5760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff166118ac576040516396e1352960e01b815260040160405180910390fd5b6001600160a01b038316600081815260a56020526040908190208054851515600160c81b0260ff60c81b19909116179055517f5fb0304a827d06fca0ab552393a60b0224e0ac91b574df99de28e8f8bf8916059061170a90851515815260200190565b6000808260038111156119245761192461405c565b03611951576001600160a01b0383166000908152609a6020526040902061194a90613567565b90506119e9565b60018260038111156119655761196561405c565b0361198b576001600160a01b0383166000908152609b6020526040902061194a90613567565b600282600381111561199f5761199f61405c565b036119c5576001600160a01b0383166000908152609c6020526040902061194a90613567565b6001600160a01b0383166000908152609d602052604090206119e690613567565b90505b92915050565b6033546001600160a01b03163314611a195760405162461bcd60e51b8152600401610b6a90613f0c565b60a154608011611a3c5760405163b285db3b60e01b815260040160405180910390fd5b6001600160a01b038316611a635760405163d92e233d60e01b815260040160405180910390fd5b61271061ffff82161180611a7c575061271061ffff8316115b15611a9a57604051631a97cb1b60e31b815260040160405180910390fd5b60aa5460405163c44b11f760e01b81526001600160a01b038581166004830152611b1a92169063c44b11f790602401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a91906140c1565b5167010000000000000016151590565b611b3757604051635807a7ab60e11b815260040160405180910390fd5b60aa546040516335ea6a7560e01b81526001600160a01b03858116600483015260009216906335ea6a759060240161018060405180830381865afa158015611b83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba79190614125565b60e001516001600160a01b038116600090815260a56020526040902054909150600160c01b900460ff1615611bef57604051631afb05cb60e31b815260040160405180910390fd5b6001600160a01b03818116600090815260a2602090815260408083206b033b2e3c9fd0803ce80000009081905560a383528184205560a490915290819020805463ffffffff19164263ffffffff1617815560aa54915163d15e005360e01b815287841660048201529092919091169063d15e005390602401602060405180830381865afa158015611c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca89190613ff8565b81546001600160701b03919091166401000000000271ffffffffffffffffffffffffffff000000001990911617815560aa5460405163386497fd60e01b81526001600160a01b0387811660048301529091169063386497fd90602401602060405180830381865afa158015611d21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d459190613ff8565b8160000160126101000a8154816001600160701b0302191690836001600160701b031602179055506040518060e00160405280866001600160a01b031681526020018561ffff1681526020018461ffff1681526020016001151581526020016000151581526020016000151581526020016000151581525060a56000846001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548161ffff021916908361ffff16021790555060608201518160000160186101000a81548160ff02191690831515021790555060808201518160000160196101000a81548160ff02191690831515021790555060a082015181600001601a6101000a81548160ff02191690831515021790555060c082015181600001601b6101000a81548160ff021916908315150217905550905050600160a180549050901b600160001b901b60a76000846001600160a01b03166001600160a01b031681526020019081526020016000208190555060a1829080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b03160217905550611f9060aa60009054906101000a90046001600160a01b0316600019876001600160a01b03166135999092919063ffffffff16565b6040805161ffff8087168252851660208201526001600160a01b038416917f411078003dc53bceaaa8a7c1d423236d5ce8eaac303e86acab168abcd3e91ffd910160405180910390a25050505050565b6002606554036120025760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808416600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015284916120ba576040516396e1352960e01b815260040160405180910390fd5b8060800151156120dd57604051630a9105a360e31b815260040160405180910390fd5b609954610ce190869086908690600160801b90046001600160401b0316613610565b600054610100900460ff1661211a5760005460ff161561211e565b303b155b6121815760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610b6a565b600054610100900460ff161580156121a3576000805461ffff19166101011790555b816000036121c45760405163275644a160e21b815260040160405180910390fd5b6121cc613653565b6121d4613682565b60ad80546001600160a01b038088166001600160a01b03199283161790925560ab80548a841690831617905560ac805489841690831617905560a88054928716929091168217905560408051630261bf8b60e01b81529051630261bf8b916004818101926020929091908290030181865afa158015612257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227b9190614212565b60aa80546001600160a01b03929092166001600160a01b03199092169190911790558251609980546020860151604087015160608801516001600160401b03908116600160c01b026001600160c01b03928216600160801b02929092166001600160801b03938216600160401b026001600160801b0319909516919096161792909217169290921791909117905560988290558015611488576000805461ff001916905550505050505050565b6033546001600160a01b031633146123525760405162461bcd60e51b8152600401610b6a90613f0c565b61235c60006136b1565b565b6033546001600160a01b031633146123885760405162461bcd60e51b8152600401610b6a90613f0c565b805160998054602084015160408086015160608701516001600160401b03908116600160c01b026001600160c01b03928216600160801b02929092166001600160801b03948216600160401b026001600160801b03199096169190971617939093179190911693909317179055517f837ae3fc1cda9774726e0150f9f2ba34b5b33716fe86de000a7e552622fed8d59061139c90839081516001600160401b039081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b60008083600381111561246e5761246e61405c565b0361249c576001600160a01b0384166000908152609a602052604090206124959083613703565b9050612537565b60018360038111156124b0576124b061405c565b036124d7576001600160a01b0384166000908152609b602052604090206124959083613703565b60028360038111156124eb576124eb61405c565b03612512576001600160a01b0384166000908152609c602052604090206124959083613703565b6001600160a01b0384166000908152609d602052604090206125349083613703565b90505b9392505050565b6033546001600160a01b031633146125685760405162461bcd60e51b8152600401610b6a90613f0c565b6097805460ff19168215159081179091556040519081527f629214570a96e8f58ccbce4488267cbe9ce88c21626ba835f9dedc9d69ab89c39060200161139c565b6033546001600160a01b031633146125d35760405162461bcd60e51b8152600401610b6a90613f0c565b60b0546001600160a01b03166125fc5760405163d92e233d60e01b815260040160405180910390fd5b8260005b8181101561280d57600086868381811061261c5761261c614046565b9050602002016020810190612631919061390a565b6001600160a01b03808216600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b830481161580156060840152600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c0820152919250806126d3575080608001515b806126df57508060a001515b156126eb5750506127fd565b80516040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015612734573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127589190613ff8565b90508060000361276b57505050506127fd565b600061279789898881811061278257612782614046565b90506020020135838082109182029115020190565b60b0549091506127b4906001600160a01b03858116911683613758565b846001600160a01b03167fbc50cfea30a46f2c6d1638717dc48ef12ab41ce93c25960f749ed48623b5aeca826040516127ef91815260200190565b60405180910390a250505050505b61280681614245565b9050612600565b505050505050565b606060a180548060200260200160405190810160405280929190818152602001828054801561286d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161284f575b5050505050905090565b6001600160a01b038116600090815260a560205260409020548190600160c01b900460ff166128b9576040516396e1352960e01b815260040160405180910390fd5b6128c2826137d0565b5050565b6002606554036128e85760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808516600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015285916129a0576040516396e1352960e01b815260040160405180910390fd5b8060800151156129c357604051630a9105a360e31b815260040160405180910390fd5b6001600160a01b03808616600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c08201528691612a76576040516396e1352960e01b815260040160405180910390fd5b806080015115612a9957604051630a9105a360e31b815260040160405180910390fd5b6040516001600160a01b03808a16602483015280891660448301528716606482015260848101869052612b1790633c8380b560e11b9060a4015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260ac546001600160a01b03169061381e565b5050600160655550505050505050565b6033546001600160a01b03163314612b515760405162461bcd60e51b8152600401610b6a90613f0c565b60ae80546001600160a01b0319166001600160a01b0383169081179091556040517f326b2e6be6f045d4eea85a41c714df3692132315a6ff6a80196817272c89aa4e90600090a250565b600260655403612bbd5760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808416600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c08201528491612c75576040516396e1352960e01b815260040160405180910390fd5b806080015180612c8657508060a001515b15612ca457604051630a9105a360e31b815260040160405180910390fd5b610ce185858561352c565b6033546001600160a01b03163314612cd95760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff16612d1b576040516396e1352960e01b815260040160405180910390fd5b6001600160a01b038316600081815260a56020526040908190208054851515600160d81b0260ff60d81b19909116179055517f8d2c76c0d7dcf49cd4c4f8a206eb0f990b10bf5635ece070fb58ce9d33a7874f9061170a90851515815260200190565b6033546001600160a01b03163314612da85760405162461bcd60e51b8152600401610b6a90613f0c565b6040516001600160a01b0383166024820152604481018290526111f190630a954c6f60e01b90606401612ad3565b6033546001600160a01b03163314612e005760405162461bcd60e51b8152600401610b6a90613f0c565b60b080546001600160a01b0319166001600160a01b0383169081179091556040517f7b23bd31f405e09a43804fe266d4b6c17f4f4369ff5f43f71452c76aa43620ac90600090a250565b6033546001600160a01b03163314612e745760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff16612eb6576040516396e1352960e01b815260040160405180910390fd5b61271061ffff83161115612edd57604051631a97cb1b60e31b815260040160405180910390fd5b612ee6836137d0565b6001600160a01b038316600081815260a56020908152604091829020805461ffff60a01b1916600160a01b61ffff88169081029190911790915591519182527f07e13f8ca204c42dabbc3599491f28193fc66fb9dac125630b2eb7c21bed9be9910161170a565b6033546001600160a01b03163314612f775760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff16612fb9576040516396e1352960e01b815260040160405180910390fd5b61271061ffff83161115612fe057604051631a97cb1b60e31b815260040160405180910390fd5b612fe9836137d0565b6001600160a01b038316600081815260a56020908152604091829020805461ffff60b01b1916600160b01b61ffff88169081029190911790915591519182527ff9da65ad6e566b695847a15f00a9b1d9a737638ec570828b2043dca63737b305910161170a565b6002606554036130725760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808316600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c0820152839161312a576040516396e1352960e01b815260040160405180910390fd5b80608001518061313b57508060a001515b1561315957604051630a9105a360e31b815260040160405180910390fd5b609954611315908590339086906001600160401b031661345f565b6033546001600160a01b0316331461319e5760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b0381166132035760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b6a565b61320c816136b1565b50565b6002606554036132315760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808316600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015283916132e9576040516396e1352960e01b815260040160405180910390fd5b80608001511561330c57604051630a9105a360e31b815260040160405180910390fd5b60995461131590859085903390600160801b90046001600160401b0316613610565b6002606554036133505760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808516600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c08201528591613408576040516396e1352960e01b815260040160405180910390fd5b80608001518061341957508060a001515b1561343757604051630a9105a360e31b815260040160405180910390fd5b6134438686868661345f565b5050600160655550505050565b6001600160a01b03163b151590565b6040516001600160a01b038086166024830152336044830152841660648201526084810183905260a481018290526134e2906385d7334d60e01b9060c4015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260ab546001600160a01b03169061381e565b5050505050565b6040516001600160a01b038086166024830152336044830152841660648201526084810183905260a481018290526134e29063c2af978760e01b9060c401612ad3565b6040516001600160a01b0384166024820152604481018390526064810182905261356190634fd5881b60e11b9060840161349e565b50505050565b80546000901561358c5761357c826001613867565b546001600160a01b031692915050565b506000919050565b919050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806135615760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606401610b6a565b6040516001600160a01b038086166024830152604482018590523360648301528316608482015260a481018290526134e290632dbcafc760e21b9060c401612ad3565b600054610100900460ff1661367a5760405162461bcd60e51b8152600401610b6a9061425e565b61235c613897565b600054610100900460ff166136a95760405162461bcd60e51b8152600401610b6a9061425e565b61235c6138c5565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0381166000908152600283016020526040812054835481101561374e5761373b846137368360016142a9565b613867565b546001600160a01b031691506119e99050565b60009150506119e9565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806135615760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610b6a565b604080516001600160a01b038381166024808401919091528351808403909101815260449092019092526020810180516001600160e01b03166328894fbb60e21b17905260ad546128c29216905b6040518151600090819060208501865af4613850573d6138475763037b81af60e11b8152600481fd5b3d6000823e3d81fd5b3d8152602081013d6000823e3d0160405292915050565b6000826138756001846142c1565b8154811061388557613885614046565b90600052602060002001905092915050565b600054610100900460ff166138be5760405162461bcd60e51b8152600401610b6a9061425e565b6001606555565b600054610100900460ff166138ec5760405162461bcd60e51b8152600401610b6a9061425e565b61235c336136b1565b6001600160a01b038116811461320c57600080fd5b60006020828403121561391c57600080fd5b8135612537816138f5565b60008060006060848603121561393c57600080fd5b8335613947816138f5565b92506020840135613957816138f5565b929592945050506040919091013590565b60008083601f84011261397a57600080fd5b5081356001600160401b0381111561399157600080fd5b6020830191508360208260051b85010111156139ac57600080fd5b9250929050565b8035801515811461359457600080fd5b6000806000604084860312156139d857600080fd5b83356001600160401b038111156139ee57600080fd5b6139fa86828701613968565b9094509250613a0d9050602085016139b3565b90509250925092565b600060208284031215613a2857600080fd5b6119e6826139b3565b60008060408385031215613a4457600080fd5b8235613a4f816138f5565b946020939093013593505050565b600060208284031215613a6f57600080fd5b5035919050565b60008060408385031215613a8957600080fd5b8235613a94816138f5565b9150613aa2602084016139b3565b90509250929050565b80356004811061359457600080fd5b60008060408385031215613acd57600080fd5b8235613ad8816138f5565b9150613aa260208401613aab565b803561ffff8116811461359457600080fd5b600080600060608486031215613b0d57600080fd5b8335613b18816138f5565b9250613b2660208501613ae6565b9150613a0d60408501613ae6565b600080600060608486031215613b4957600080fd5b8335613b54816138f5565b9250602084013591506040840135613b6b816138f5565b809150509250925092565b60405161018081016001600160401b0381118282101715613ba757634e487b7160e01b600052604160045260246000fd5b60405290565b80356001600160401b038116811461359457600080fd5b600060808284031215613bd657600080fd5b604051608081018181106001600160401b0382111715613c0657634e487b7160e01b600052604160045260246000fd5b604052905080613c1583613bad565b8152613c2360208401613bad565b6020820152613c3460408401613bad565b6040820152613c4560608401613bad565b60608201525092915050565b6000806000806000806101208789031215613c6b57600080fd5b8635613c76816138f5565b95506020870135613c86816138f5565b94506040870135613c96816138f5565b93506060870135613ca6816138f5565b9250613cb58860808901613bc4565b915061010087013590509295509295509295565b600060808284031215613cdb57600080fd5b6119e68383613bc4565b600080600060608486031215613cfa57600080fd5b8335613d05816138f5565b9250613d1360208501613aab565b91506040840135613b6b816138f5565b60008060008060408587031215613d3957600080fd5b84356001600160401b0380821115613d5057600080fd5b613d5c88838901613968565b90965094506020870135915080821115613d7557600080fd5b50613d8287828801613968565b95989497509550505050565b60008060408385031215613da157600080fd5b8235613dac816138f5565b91506020830135613dbc816138f5565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613e085783516001600160a01b031683529284019291840191600101613de3565b50909695505050505050565b60008060008060808587031215613e2a57600080fd5b8435613e35816138f5565b93506020850135613e45816138f5565b92506040850135613e55816138f5565b9396929550929360600135925050565b600080600060608486031215613e7a57600080fd5b8335613e85816138f5565b95602085013595506040909401359392505050565b60008060408385031215613ead57600080fd5b8235613eb8816138f5565b9150613aa260208401613ae6565b60008060008060808587031215613edc57600080fd5b8435613ee7816138f5565b93506020850135613ef7816138f5565b93969395505050506040820135916060013590565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b8183526000602080850194508260005b85811015613fb6578135613f9b816138f5565b6001600160a01b031687529582019590820190600101613f88565b509495945050505050565b600060018060a01b03808716835260606020840152613fe4606084018688613f78565b915080841660408401525095945050505050565b60006020828403121561400a57600080fd5b5051919050565b606081526000614025606083018688613f78565b6020830194909452506001600160a01b039190911660409091015292915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60006020828403121561408457600080fd5b604051602081018181106001600160401b03821117156140b457634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b6000602082840312156140d357600080fd5b6119e68383614072565b80516001600160801b038116811461359457600080fd5b805164ffffffffff8116811461359457600080fd5b8051613594816138f5565b805160ff8116811461359457600080fd5b6000610180828403121561413857600080fd5b614140613b76565b61414a8484614072565b8152614158602084016140dd565b6020820152614169604084016140dd565b604082015261417a606084016140dd565b606082015261418b608084016140dd565b608082015261419c60a084016140dd565b60a08201526141ad60c084016140f4565b60c08201526141be60e08401614109565b60e08201526101006141d1818501614109565b908201526101206141e3848201614109565b908201526101406141f5848201614109565b90820152610160614207848201614114565b908201529392505050565b60006020828403121561422457600080fd5b8151612537816138f5565b634e487b7160e01b600052601160045260246000fd5b6000600182016142575761425761422f565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600082198211156142bc576142bc61422f565b500190565b6000828210156142d3576142d361422f565b50039056fea264697066735822122020040c63d64b7e002862304c341b2ff80c3a400aaa54ff795ec1f437295028e264736f6c634300080d0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103fc5760003560e01c8063947574ac11610215578063caf642f911610125578063e61c6d6f116100b8578063f3fef3a311610087578063f3fef3a314610ae3578063f4ea93d814610af6578063f62256c714610b12578063f8180c6614610b25578063fb8b758d14610b3857600080fd5b8063e61c6d6f14610a4f578063f2b9fdb814610a58578063f2f4ca1614610a6b578063f2fde38b14610ad057600080fd5b8063defe2053116100f4578063defe2053146109e4578063df303f8a146109f7578063e501ed0414610a0a578063e5a602ac14610a3c57600080fd5b8063caf642f914610998578063cb830d03146109ab578063d5f80c34146109c8578063d664f72c146109db57600080fd5b8063b24be687116101a8578063c1bce0b711610177578063c1bce0b714610948578063c2ee3a081461095b578063c3525c2814610963578063c72c4d1014610972578063c7a5b9831461098557600080fd5b8063b24be687146108db578063b505e7a2146108ee578063b650f86d14610915578063bc45d1901461092857600080fd5b8063a1d6000c116101e4578063a1d6000c1461088d578063a2253eec146108a2578063aab3f868146108b5578063af8b1c6f146108c857600080fd5b8063947574ac146107315780639f382f6a14610778578063a086fc2214610830578063a10c02501461088557600080fd5b806341bb0725116103105780636ade4661116102a35780637f3ad056116102725780637f3ad056146106c757806380a67a7d146106da578063854f7ebb146106ed5780638da5cb5b1461070d5780639023951b1461071e57600080fd5b80636ade466114610686578063715018a6146106995780637683a908146106a1578063789caa3e146106b457600080fd5b80635f2475ca116102df5780635f2475ca146105de57806361749c98146105f1578063661cd5fc1461060457806369328dec1461067357600080fd5b806341bb0725146105925780634b8a3529146105a5578063582d44bb146105b85780635acff027146105cb57600080fd5b80632ebf4be011610393578063381adc6b11610362578063381adc6b146105265780633b0a79ec146105465780633c42c3b7146105595780633cfe57381461056c578063411302501461057f57600080fd5b80632ebf4be0146104c65780632ff34fe1146104e657806331bc9959146104f9578063361399f41461051357600080fd5b806316f0115b116103cf57806316f0115b146104625780631da649cf1461048d5780631f3d2e6e146104a057806322867d78146104b357600080fd5b80630a8ddc5e146104015780630c0a769b146104165780630cda22dc14610429578063148e23ce1461043c575b600080fd5b61041461040f36600461390a565b610b40565b005b610414610424366004613927565b610bbd565b61041461043736600461390a565b610ced565b61044f61044a3660046139c3565b610d88565b6040519081526020015b60405180910390f35b60aa54610475906001600160a01b031681565b6040516001600160a01b039091168152602001610459565b61041461049b366004613927565b611008565b6104146104ae366004613a16565b611127565b6104146104c1366004613a31565b6111f6565b61044f6104d436600461390a565b60a36020526000908152604090205481565b6104146104f4366004613a5d565b611320565b610501600081565b60405160ff9091168152602001610459565b610414610521366004613a76565b6113a7565b61044f61053436600461390a565b60a76020526000908152604090205481565b60ac54610475906001600160a01b031681565b61041461056736600461390a565b611491565b61041461057a36600461390a565b61152c565b61041461058d36600461390a565b6115a0565b6104146105a0366004613a76565b61163b565b6104146105b3366004613a31565b611717565b6104146105c6366004613a76565b611840565b6104756105d9366004613aba565b61190f565b60a954610475906001600160a01b031681565b6104146105ff366004613af8565b6119ef565b61064761061236600461390a565b60a46020526000908152604090205463ffffffff8116906001600160701b036401000000008204811691600160901b90041683565b6040805163ffffffff90941684526001600160701b039283166020850152911690820152606001610459565b610414610681366004613b34565b611fe0565b610414610694366004613c51565b6120ff565b610414612328565b6104146106af366004613cc9565b61235e565b6104756106c2366004613ce5565b612459565b60ad54610475906001600160a01b031681565b6104146106e8366004613a16565b61253e565b61044f6106fb36600461390a565b60a26020526000908152604090205481565b6033546001600160a01b0316610475565b61041461072c366004613d23565b6125a9565b61076361073f366004613d8e565b609f6020908152600092835260408084209091529082529020805460019091015482565b60408051928352602083019190915201610459565b6107e361078636600461390a565b60a5602052600090815260409020546001600160a01b0381169061ffff600160a01b8204811691600160b01b81049091169060ff600160c01b8204811691600160c81b8104821691600160d01b8204811691600160d81b90041687565b604080516001600160a01b03909816885261ffff9687166020890152959094169486019490945290151560608501521515608084015290151560a0830152151560c082015260e001610459565b61086561083e36600461390a565b60a66020526000908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610459565b610501600281565b610895612815565b6040516104599190613dc7565b6104146108b036600461390a565b612877565b6104146108c3366004613e14565b6128c6565b60b054610475906001600160a01b031681565b60ae54610475906001600160a01b031681565b61044f7f555555555555555555555555555555555555555555555555555555555555555581565b61041461092336600461390a565b612b27565b61044f61093636600461390a565b60a06020526000908152604090205481565b610414610956366004613e65565b612b9b565b61044f600181565b61044f670de0b6b3a764000081565b60a854610475906001600160a01b031681565b610414610993366004613a76565b612caf565b6104146109a6366004613a31565b612d7e565b6097546109b89060ff1681565b6040519015158152602001610459565b6104146109d636600461390a565b612dd6565b61044f61138881565b60af54610475906001600160a01b031681565b610414610a05366004613e9a565b612e4a565b610763610a18366004613d8e565b609e6020908152600092835260408084209091529082529020805460019091015482565b610414610a4a366004613e9a565b612f4d565b61044f60985481565b610414610a66366004613a31565b613050565b609954610a9d906001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b604080516001600160401b0395861681529385166020850152918416918301919091529091166060820152608001610459565b610414610ade36600461390a565b613174565b610414610af1366004613a31565b61320f565b610aff61271081565b60405161ffff9091168152602001610459565b610414610b20366004613ec6565b61332e565b60ab54610475906001600160a01b031681565b61044f608081565b6033546001600160a01b03163314610b735760405162461bcd60e51b8152600401610b6a90613f0c565b60405180910390fd5b60af80546001600160a01b0319166001600160a01b0383169081179091556040517f22597c132d394cddf8eee9722c4dfc456da51de4c9d9cdf2b8f2523ae0e7eb8190600090a250565b600260655403610bdf5760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808416600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c08201528491610c97576040516396e1352960e01b815260040160405180910390fd5b806080015180610ca857508060a001515b15610cc657604051630a9105a360e31b815260040160405180910390fd5b609954610ce1908690869086906001600160401b031661345f565b50506001606555505050565b6033546001600160a01b03163314610d175760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038116610d3e5760405163d92e233d60e01b815260040160405180910390fd5b60ab80546001600160a01b0319166001600160a01b0383169081179091556040517f7c0388b4f238710366ef8639dfdbad78e473a2b381ddde99fdcb50de646bf51090600090a250565b6000600260655403610dac5760405162461bcd60e51b8152600401610b6a90613f41565b600260655560975460ff1615610dd557604051633be92ecd60e21b815260040160405180910390fd5b60af5460a954604051632b70a16560e11b81526001600160a01b03928316926356e142ca92610e0f92911690889088903390600401613fc1565b6020604051808303816000875af1158015610e2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e529190613ff8565b90508015610ffc578115610f475760a95460ae54604051633111e7b360e01b81526001600160a01b0392831692633111e7b392610e9a92899289928892911690600401614011565b6020604051808303816000875af1158015610eb9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edd9190613ff8565b5060ae546040516308c487b560e41b8152336004820152602481018390526001600160a01b0390911690638c487b5090604401600060405180830381600087803b158015610f2a57600080fd5b505af1158015610f3e573d6000803e3d6000fd5b50505050610fc2565b60a954604051633111e7b360e01b81526001600160a01b0390911690633111e7b390610f7d908790879086903390600401614011565b6020604051808303816000875af1158015610f9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc09190613ff8565b505b6040518181528215159033907fab3c4ae116d5285676cffaad9c32cae8acf49b49ca0fc9953b029f97acb955ef9060200160405180910390a35b60016065559392505050565b60026065540361102a5760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808416600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015284916110e2576040516396e1352960e01b815260040160405180910390fd5b80608001511561110557604051630a9105a360e31b815260040160405180910390fd5b609954610ce190869086908690600160c01b90046001600160401b03166134e9565b6033546001600160a01b031633146111515760405162461bcd60e51b8152600401610b6a90613f0c565b60a15460005b818110156111f157600060a1828154811061117457611174614046565b6000918252602080832091909101546001600160a01b031680835260a58252604092839020805460ff60c81b1916600160c81b891515908102919091179091559251928352925082917f5fb0304a827d06fca0ab552393a60b0224e0ac91b574df99de28e8f8bf891605910160405180910390a250600101611157565b505050565b6002606554036112185760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808316600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015283916112d0576040516396e1352960e01b815260040160405180910390fd5b8060800151156112f357604051630a9105a360e31b815260040160405180910390fd5b60995461131590859033908690600160c01b90046001600160401b03166134e9565b505060016065555050565b6033546001600160a01b0316331461134a5760405162461bcd60e51b8152600401610b6a90613f0c565b8060000361136b5760405163275644a160e21b815260040160405180910390fd5b60988190556040518181527f51f9468910070fc9ae906e375f46182f4f84ab311131794a3eceb0b6b80e7f1b906020015b60405180910390a150565b6033546001600160a01b031633146113d15760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff16611413576040516396e1352960e01b815260040160405180910390fd5b60aa546001600160a01b03848116600090815260a5602052604090819020549051635a3b74b960e01b815290821660048201528415156024820152911690635a3b74b990604401600060405180830381600087803b15801561147457600080fd5b505af1158015611488573d6000803e3d6000fd5b50505050505050565b6033546001600160a01b031633146114bb5760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b0381166114e25760405163d92e233d60e01b815260040160405180910390fd5b60ac80546001600160a01b0319166001600160a01b0383169081179091556040517f3dcc0a66d404037e318c6af57572c7f3dfe9250a0a58df79167e76795027946d90600090a250565b6033546001600160a01b031633146115565760405162461bcd60e51b8152600401610b6a90613f0c565b60a980546001600160a01b0319166001600160a01b0383169081179091556040517f9f43a60bcf56fe19c6ef946464526881d6871673d5b8e62fb4df922882abcb4990600090a250565b6033546001600160a01b031633146115ca5760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b0381166115f15760405163d92e233d60e01b815260040160405180910390fd5b60ad80546001600160a01b0319166001600160a01b0383169081179091556040517fc1a4bb1bd557bbfbac2d5702ef3fd93590f2c98c8ccc7f4200564e5992a2aaa590600090a250565b6033546001600160a01b031633146116655760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff166116a7576040516396e1352960e01b815260040160405180910390fd5b6001600160a01b038316600081815260a56020526040908190208054851515600160d01b0260ff60d01b19909116179055517f5024f94e1f582131506b852f4d0aaaaf1c4f03825397c5e64da730ada4e2437a9061170a90851515815260200190565b60405180910390a2505050565b6002606554036117395760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808316600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015283916117f1576040516396e1352960e01b815260040160405180910390fd5b80608001518061180257508060a001515b1561182057604051630a9105a360e31b815260040160405180910390fd5b6099546113159085908590600160401b90046001600160401b031661352c565b6033546001600160a01b0316331461186a5760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff166118ac576040516396e1352960e01b815260040160405180910390fd5b6001600160a01b038316600081815260a56020526040908190208054851515600160c81b0260ff60c81b19909116179055517f5fb0304a827d06fca0ab552393a60b0224e0ac91b574df99de28e8f8bf8916059061170a90851515815260200190565b6000808260038111156119245761192461405c565b03611951576001600160a01b0383166000908152609a6020526040902061194a90613567565b90506119e9565b60018260038111156119655761196561405c565b0361198b576001600160a01b0383166000908152609b6020526040902061194a90613567565b600282600381111561199f5761199f61405c565b036119c5576001600160a01b0383166000908152609c6020526040902061194a90613567565b6001600160a01b0383166000908152609d602052604090206119e690613567565b90505b92915050565b6033546001600160a01b03163314611a195760405162461bcd60e51b8152600401610b6a90613f0c565b60a154608011611a3c5760405163b285db3b60e01b815260040160405180910390fd5b6001600160a01b038316611a635760405163d92e233d60e01b815260040160405180910390fd5b61271061ffff82161180611a7c575061271061ffff8316115b15611a9a57604051631a97cb1b60e31b815260040160405180910390fd5b60aa5460405163c44b11f760e01b81526001600160a01b038581166004830152611b1a92169063c44b11f790602401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a91906140c1565b5167010000000000000016151590565b611b3757604051635807a7ab60e11b815260040160405180910390fd5b60aa546040516335ea6a7560e01b81526001600160a01b03858116600483015260009216906335ea6a759060240161018060405180830381865afa158015611b83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba79190614125565b60e001516001600160a01b038116600090815260a56020526040902054909150600160c01b900460ff1615611bef57604051631afb05cb60e31b815260040160405180910390fd5b6001600160a01b03818116600090815260a2602090815260408083206b033b2e3c9fd0803ce80000009081905560a383528184205560a490915290819020805463ffffffff19164263ffffffff1617815560aa54915163d15e005360e01b815287841660048201529092919091169063d15e005390602401602060405180830381865afa158015611c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca89190613ff8565b81546001600160701b03919091166401000000000271ffffffffffffffffffffffffffff000000001990911617815560aa5460405163386497fd60e01b81526001600160a01b0387811660048301529091169063386497fd90602401602060405180830381865afa158015611d21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d459190613ff8565b8160000160126101000a8154816001600160701b0302191690836001600160701b031602179055506040518060e00160405280866001600160a01b031681526020018561ffff1681526020018461ffff1681526020016001151581526020016000151581526020016000151581526020016000151581525060a56000846001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548161ffff021916908361ffff16021790555060608201518160000160186101000a81548160ff02191690831515021790555060808201518160000160196101000a81548160ff02191690831515021790555060a082015181600001601a6101000a81548160ff02191690831515021790555060c082015181600001601b6101000a81548160ff021916908315150217905550905050600160a180549050901b600160001b901b60a76000846001600160a01b03166001600160a01b031681526020019081526020016000208190555060a1829080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b03160217905550611f9060aa60009054906101000a90046001600160a01b0316600019876001600160a01b03166135999092919063ffffffff16565b6040805161ffff8087168252851660208201526001600160a01b038416917f411078003dc53bceaaa8a7c1d423236d5ce8eaac303e86acab168abcd3e91ffd910160405180910390a25050505050565b6002606554036120025760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808416600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015284916120ba576040516396e1352960e01b815260040160405180910390fd5b8060800151156120dd57604051630a9105a360e31b815260040160405180910390fd5b609954610ce190869086908690600160801b90046001600160401b0316613610565b600054610100900460ff1661211a5760005460ff161561211e565b303b155b6121815760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610b6a565b600054610100900460ff161580156121a3576000805461ffff19166101011790555b816000036121c45760405163275644a160e21b815260040160405180910390fd5b6121cc613653565b6121d4613682565b60ad80546001600160a01b038088166001600160a01b03199283161790925560ab80548a841690831617905560ac805489841690831617905560a88054928716929091168217905560408051630261bf8b60e01b81529051630261bf8b916004818101926020929091908290030181865afa158015612257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227b9190614212565b60aa80546001600160a01b03929092166001600160a01b03199092169190911790558251609980546020860151604087015160608801516001600160401b03908116600160c01b026001600160c01b03928216600160801b02929092166001600160801b03938216600160401b026001600160801b0319909516919096161792909217169290921791909117905560988290558015611488576000805461ff001916905550505050505050565b6033546001600160a01b031633146123525760405162461bcd60e51b8152600401610b6a90613f0c565b61235c60006136b1565b565b6033546001600160a01b031633146123885760405162461bcd60e51b8152600401610b6a90613f0c565b805160998054602084015160408086015160608701516001600160401b03908116600160c01b026001600160c01b03928216600160801b02929092166001600160801b03948216600160401b026001600160801b03199096169190971617939093179190911693909317179055517f837ae3fc1cda9774726e0150f9f2ba34b5b33716fe86de000a7e552622fed8d59061139c90839081516001600160401b039081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b60008083600381111561246e5761246e61405c565b0361249c576001600160a01b0384166000908152609a602052604090206124959083613703565b9050612537565b60018360038111156124b0576124b061405c565b036124d7576001600160a01b0384166000908152609b602052604090206124959083613703565b60028360038111156124eb576124eb61405c565b03612512576001600160a01b0384166000908152609c602052604090206124959083613703565b6001600160a01b0384166000908152609d602052604090206125349083613703565b90505b9392505050565b6033546001600160a01b031633146125685760405162461bcd60e51b8152600401610b6a90613f0c565b6097805460ff19168215159081179091556040519081527f629214570a96e8f58ccbce4488267cbe9ce88c21626ba835f9dedc9d69ab89c39060200161139c565b6033546001600160a01b031633146125d35760405162461bcd60e51b8152600401610b6a90613f0c565b60b0546001600160a01b03166125fc5760405163d92e233d60e01b815260040160405180910390fd5b8260005b8181101561280d57600086868381811061261c5761261c614046565b9050602002016020810190612631919061390a565b6001600160a01b03808216600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b830481161580156060840152600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c0820152919250806126d3575080608001515b806126df57508060a001515b156126eb5750506127fd565b80516040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015612734573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127589190613ff8565b90508060000361276b57505050506127fd565b600061279789898881811061278257612782614046565b90506020020135838082109182029115020190565b60b0549091506127b4906001600160a01b03858116911683613758565b846001600160a01b03167fbc50cfea30a46f2c6d1638717dc48ef12ab41ce93c25960f749ed48623b5aeca826040516127ef91815260200190565b60405180910390a250505050505b61280681614245565b9050612600565b505050505050565b606060a180548060200260200160405190810160405280929190818152602001828054801561286d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161284f575b5050505050905090565b6001600160a01b038116600090815260a560205260409020548190600160c01b900460ff166128b9576040516396e1352960e01b815260040160405180910390fd5b6128c2826137d0565b5050565b6002606554036128e85760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808516600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015285916129a0576040516396e1352960e01b815260040160405180910390fd5b8060800151156129c357604051630a9105a360e31b815260040160405180910390fd5b6001600160a01b03808616600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c08201528691612a76576040516396e1352960e01b815260040160405180910390fd5b806080015115612a9957604051630a9105a360e31b815260040160405180910390fd5b6040516001600160a01b03808a16602483015280891660448301528716606482015260848101869052612b1790633c8380b560e11b9060a4015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260ac546001600160a01b03169061381e565b5050600160655550505050505050565b6033546001600160a01b03163314612b515760405162461bcd60e51b8152600401610b6a90613f0c565b60ae80546001600160a01b0319166001600160a01b0383169081179091556040517f326b2e6be6f045d4eea85a41c714df3692132315a6ff6a80196817272c89aa4e90600090a250565b600260655403612bbd5760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808416600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c08201528491612c75576040516396e1352960e01b815260040160405180910390fd5b806080015180612c8657508060a001515b15612ca457604051630a9105a360e31b815260040160405180910390fd5b610ce185858561352c565b6033546001600160a01b03163314612cd95760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff16612d1b576040516396e1352960e01b815260040160405180910390fd5b6001600160a01b038316600081815260a56020526040908190208054851515600160d81b0260ff60d81b19909116179055517f8d2c76c0d7dcf49cd4c4f8a206eb0f990b10bf5635ece070fb58ce9d33a7874f9061170a90851515815260200190565b6033546001600160a01b03163314612da85760405162461bcd60e51b8152600401610b6a90613f0c565b6040516001600160a01b0383166024820152604481018290526111f190630a954c6f60e01b90606401612ad3565b6033546001600160a01b03163314612e005760405162461bcd60e51b8152600401610b6a90613f0c565b60b080546001600160a01b0319166001600160a01b0383169081179091556040517f7b23bd31f405e09a43804fe266d4b6c17f4f4369ff5f43f71452c76aa43620ac90600090a250565b6033546001600160a01b03163314612e745760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff16612eb6576040516396e1352960e01b815260040160405180910390fd5b61271061ffff83161115612edd57604051631a97cb1b60e31b815260040160405180910390fd5b612ee6836137d0565b6001600160a01b038316600081815260a56020908152604091829020805461ffff60a01b1916600160a01b61ffff88169081029190911790915591519182527f07e13f8ca204c42dabbc3599491f28193fc66fb9dac125630b2eb7c21bed9be9910161170a565b6033546001600160a01b03163314612f775760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b038216600090815260a560205260409020548290600160c01b900460ff16612fb9576040516396e1352960e01b815260040160405180910390fd5b61271061ffff83161115612fe057604051631a97cb1b60e31b815260040160405180910390fd5b612fe9836137d0565b6001600160a01b038316600081815260a56020908152604091829020805461ffff60b01b1916600160b01b61ffff88169081029190911790915591519182527ff9da65ad6e566b695847a15f00a9b1d9a737638ec570828b2043dca63737b305910161170a565b6002606554036130725760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808316600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c0820152839161312a576040516396e1352960e01b815260040160405180910390fd5b80608001518061313b57508060a001515b1561315957604051630a9105a360e31b815260040160405180910390fd5b609954611315908590339086906001600160401b031661345f565b6033546001600160a01b0316331461319e5760405162461bcd60e51b8152600401610b6a90613f0c565b6001600160a01b0381166132035760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b6a565b61320c816136b1565b50565b6002606554036132315760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808316600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c082015283916132e9576040516396e1352960e01b815260040160405180910390fd5b80608001511561330c57604051630a9105a360e31b815260040160405180910390fd5b60995461131590859085903390600160801b90046001600160401b0316613610565b6002606554036133505760405162461bcd60e51b8152600401610b6a90613f41565b60026065556001600160a01b03808516600090815260a56020908152604091829020825160e0810184529054938416815261ffff600160a01b8504811692820192909252600160b01b84049091169181019190915260ff600160c01b83048116151560608301819052600160c81b8404821615156080840152600160d01b84048216151560a0840152600160d81b90930416151560c08201528591613408576040516396e1352960e01b815260040160405180910390fd5b80608001518061341957508060a001515b1561343757604051630a9105a360e31b815260040160405180910390fd5b6134438686868661345f565b5050600160655550505050565b6001600160a01b03163b151590565b6040516001600160a01b038086166024830152336044830152841660648201526084810183905260a481018290526134e2906385d7334d60e01b9060c4015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260ab546001600160a01b03169061381e565b5050505050565b6040516001600160a01b038086166024830152336044830152841660648201526084810183905260a481018290526134e29063c2af978760e01b9060c401612ad3565b6040516001600160a01b0384166024820152604481018390526064810182905261356190634fd5881b60e11b9060840161349e565b50505050565b80546000901561358c5761357c826001613867565b546001600160a01b031692915050565b506000919050565b919050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806135615760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606401610b6a565b6040516001600160a01b038086166024830152604482018590523360648301528316608482015260a481018290526134e290632dbcafc760e21b9060c401612ad3565b600054610100900460ff1661367a5760405162461bcd60e51b8152600401610b6a9061425e565b61235c613897565b600054610100900460ff166136a95760405162461bcd60e51b8152600401610b6a9061425e565b61235c6138c5565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0381166000908152600283016020526040812054835481101561374e5761373b846137368360016142a9565b613867565b546001600160a01b031691506119e99050565b60009150506119e9565b600060405163a9059cbb60e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806135615760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152606401610b6a565b604080516001600160a01b038381166024808401919091528351808403909101815260449092019092526020810180516001600160e01b03166328894fbb60e21b17905260ad546128c29216905b6040518151600090819060208501865af4613850573d6138475763037b81af60e11b8152600481fd5b3d6000823e3d81fd5b3d8152602081013d6000823e3d0160405292915050565b6000826138756001846142c1565b8154811061388557613885614046565b90600052602060002001905092915050565b600054610100900460ff166138be5760405162461bcd60e51b8152600401610b6a9061425e565b6001606555565b600054610100900460ff166138ec5760405162461bcd60e51b8152600401610b6a9061425e565b61235c336136b1565b6001600160a01b038116811461320c57600080fd5b60006020828403121561391c57600080fd5b8135612537816138f5565b60008060006060848603121561393c57600080fd5b8335613947816138f5565b92506020840135613957816138f5565b929592945050506040919091013590565b60008083601f84011261397a57600080fd5b5081356001600160401b0381111561399157600080fd5b6020830191508360208260051b85010111156139ac57600080fd5b9250929050565b8035801515811461359457600080fd5b6000806000604084860312156139d857600080fd5b83356001600160401b038111156139ee57600080fd5b6139fa86828701613968565b9094509250613a0d9050602085016139b3565b90509250925092565b600060208284031215613a2857600080fd5b6119e6826139b3565b60008060408385031215613a4457600080fd5b8235613a4f816138f5565b946020939093013593505050565b600060208284031215613a6f57600080fd5b5035919050565b60008060408385031215613a8957600080fd5b8235613a94816138f5565b9150613aa2602084016139b3565b90509250929050565b80356004811061359457600080fd5b60008060408385031215613acd57600080fd5b8235613ad8816138f5565b9150613aa260208401613aab565b803561ffff8116811461359457600080fd5b600080600060608486031215613b0d57600080fd5b8335613b18816138f5565b9250613b2660208501613ae6565b9150613a0d60408501613ae6565b600080600060608486031215613b4957600080fd5b8335613b54816138f5565b9250602084013591506040840135613b6b816138f5565b809150509250925092565b60405161018081016001600160401b0381118282101715613ba757634e487b7160e01b600052604160045260246000fd5b60405290565b80356001600160401b038116811461359457600080fd5b600060808284031215613bd657600080fd5b604051608081018181106001600160401b0382111715613c0657634e487b7160e01b600052604160045260246000fd5b604052905080613c1583613bad565b8152613c2360208401613bad565b6020820152613c3460408401613bad565b6040820152613c4560608401613bad565b60608201525092915050565b6000806000806000806101208789031215613c6b57600080fd5b8635613c76816138f5565b95506020870135613c86816138f5565b94506040870135613c96816138f5565b93506060870135613ca6816138f5565b9250613cb58860808901613bc4565b915061010087013590509295509295509295565b600060808284031215613cdb57600080fd5b6119e68383613bc4565b600080600060608486031215613cfa57600080fd5b8335613d05816138f5565b9250613d1360208501613aab565b91506040840135613b6b816138f5565b60008060008060408587031215613d3957600080fd5b84356001600160401b0380821115613d5057600080fd5b613d5c88838901613968565b90965094506020870135915080821115613d7557600080fd5b50613d8287828801613968565b95989497509550505050565b60008060408385031215613da157600080fd5b8235613dac816138f5565b91506020830135613dbc816138f5565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613e085783516001600160a01b031683529284019291840191600101613de3565b50909695505050505050565b60008060008060808587031215613e2a57600080fd5b8435613e35816138f5565b93506020850135613e45816138f5565b92506040850135613e55816138f5565b9396929550929360600135925050565b600080600060608486031215613e7a57600080fd5b8335613e85816138f5565b95602085013595506040909401359392505050565b60008060408385031215613ead57600080fd5b8235613eb8816138f5565b9150613aa260208401613ae6565b60008060008060808587031215613edc57600080fd5b8435613ee7816138f5565b93506020850135613ef7816138f5565b93969395505050506040820135916060013590565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b8183526000602080850194508260005b85811015613fb6578135613f9b816138f5565b6001600160a01b031687529582019590820190600101613f88565b509495945050505050565b600060018060a01b03808716835260606020840152613fe4606084018688613f78565b915080841660408401525095945050505050565b60006020828403121561400a57600080fd5b5051919050565b606081526000614025606083018688613f78565b6020830194909452506001600160a01b039190911660409091015292915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60006020828403121561408457600080fd5b604051602081018181106001600160401b03821117156140b457634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b6000602082840312156140d357600080fd5b6119e68383614072565b80516001600160801b038116811461359457600080fd5b805164ffffffffff8116811461359457600080fd5b8051613594816138f5565b805160ff8116811461359457600080fd5b6000610180828403121561413857600080fd5b614140613b76565b61414a8484614072565b8152614158602084016140dd565b6020820152614169604084016140dd565b604082015261417a606084016140dd565b606082015261418b608084016140dd565b608082015261419c60a084016140dd565b60a08201526141ad60c084016140f4565b60c08201526141be60e08401614109565b60e08201526101006141d1818501614109565b908201526101206141e3848201614109565b908201526101406141f5848201614109565b90820152610160614207848201614114565b908201529392505050565b60006020828403121561422457600080fd5b8151612537816138f5565b634e487b7160e01b600052601160045260246000fd5b6000600182016142575761425761422f565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600082198211156142bc576142bc61422f565b500190565b6000828210156142d3576142d361422f565b50039056fea264697066735822122020040c63d64b7e002862304c341b2ff80c3a400aaa54ff795ec1f437295028e264736f6c634300080d0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.