Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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:
PoolFlex
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 10 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IPoolFlex.sol"; import "./interfaces/IVault.sol"; import "./interfaces/IPoolRegistry.sol"; import "./interfaces/IServiceConfigurationV3.sol"; import "./interfaces/IPoolAccessControl.sol"; import "./factories/interfaces/IPoolAccessControlFactory.sol"; import "./factories/interfaces/IBusinessDayRegistryFactory.sol"; import "./controllers/interfaces/IWithdrawDepositControllerFlex.sol"; import "./controllers/interfaces/IPoolControllerFlex.sol"; import "./factories/interfaces/IWithdrawDepositControllerFactoryFlex.sol"; import "./factories/interfaces/IPoolControllerFactoryFlex.sol"; import "./factories/interfaces/IVaultFactory.sol"; import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import "./libraries/PoolLibFlex.sol"; import "./upgrades/BeaconImplementation.sol"; /** * @title Liquidity pool for Perimeter. * @dev Used through a beacon proxy. */ contract PoolFlex is IPoolFlex, ERC20Upgradeable, BeaconImplementation { using SafeERC20Upgradeable for IERC20Upgradeable; using SafeMath for uint256; using EnumerableSet for EnumerableSet.AddressSet; /** * @dev The reference to the access control contract */ IPoolAccessControl public poolAccessControl; uint256 private todo = 666; IPoolType private _poolType; event PoolCreated(); event PoolDeposit( address indexed lender, uint256 assets, uint256 shares, uint256 transferInDayTimestamp ); event RedeemRequested( address indexed lender, uint256 assets, uint256 shares ); event RedeemReleased( address indexed lender, uint256 shares, uint256 assets ); event RepayLoanToLender( address indexed lender, uint256 indexed eventId, uint256 shares, uint256 assets ); event RepayToPoolProcessed( address indexed lender, uint256 indexed eventId, uint256 shares, uint256 assets ); event Redeem(address indexed lender, uint256 shares, uint256 assets); /** * @dev Reference to the global service configuration. */ IServiceConfigurationV3 private _serviceConfiguration; /** * @dev Reference to the underlying liquidity asset for the pool. */ IERC20Upgradeable private _liquidityAsset; /** * @dev Various accounting statistics updated throughout the pool lifetime. */ IPoolAccountingsFlex private _accountings; /** * @dev Reference to the withdraw controller for the pool. */ IWithdrawDepositControllerFlex public withdrawDepositController; /** * @dev Reference to the admin's controller for the pool. */ IPoolControllerFlex public poolController; IBusinessDayRegistry public businessDayRegistry; /** * @inheritdoc IPoolBase */ uint256 public activatedAt; error ZeroDeposit(uint256, uint256, address); error ExceedsMaxDeposit(uint256, uint256, address); error ExcessWithdraw(uint256, uint256, uint256); error NotPoolController(); error NotWithdrawController(); error NotLender(); error NotBorrowerManager(); error NotPoolAdmin(); error PoolNotActive(); error InvalidAccess(); error InvalidLoan(); error PoolInvalidState(); error PoolPaused(); error TransferDisabled(); error AccuralCalledTooEarly(uint256, uint256); error ExcessFeePayment(); error InvalidPoolSetting(); error InvalidRepayment(); /** * @dev Modifier to ensure only the PoolController calls a method. */ modifier onlyPoolController() { if (msg.sender != address(poolController)) revert NotPoolController(); _; } /** * @dev Modifier that checks that the caller is a pool lender */ modifier onlyLenderWithPPT() { if (balanceOf(msg.sender) <= 0) revert NotLender(); _; } /** * @dev Modifier to check that the pool has ever been activated */ modifier onlyActivatedPool() { if (activatedAt == 0) revert PoolNotActive(); _; } modifier onlyWithdrawController() { if (msg.sender != address(withdrawDepositController)) revert NotWithdrawController(); _; } modifier onlyAutomationOrAdmin() { if ( !_serviceConfiguration.isAutomation(msg.sender) && !_serviceConfiguration.isPoolAdmin(msg.sender) ) revert NotPoolAdmin(); _; } /** * @dev Modifier to check that the protocol is not paused */ modifier onlyNotPaused() { if (_serviceConfiguration.paused() == true) revert PoolPaused(); _; } /** * @dev Modifier that checks that the pool is Initialized or Active */ modifier atState(IPoolLifeCycleStateFlex state_) { if (poolController.state() != state_) revert PoolInvalidState(); _; } function version() public pure returns (uint16) { return 256 * 1 + 0; } function decimals() public pure override returns (uint8) { return 6; } function updatePoolData() internal { IPoolRegistry(_serviceConfiguration.getPoolRegistry()).updatePoolData( address(this) ); } modifier onlyPermittedLender() { if (!poolAccessControl.isAllowed(msg.sender)) revert NotLender(); if ( IPoolControllerFlex(poolController).borrowerManagerAddr() == msg.sender ) revert NotLender(); _; } modifier onlyBorrowerManger() { if ( !_serviceConfiguration.isBorrower(msg.sender) || IPoolControllerFlex(poolController).borrowerManagerAddr() != msg.sender ) revert NotBorrowerManager(); _; } modifier onlyPoolAdmin() { if ( !_serviceConfiguration.isPoolAdmin(msg.sender) || IPoolControllerFlex(poolController).admin() != msg.sender ) revert NotPoolAdmin(); _; } function isPermittedLender(address receiver) public view returns (bool) { return poolAccessControl.isAllowed(receiver); } /** * @dev Initializer for Pool * @param poolSettings configurable settings for the pool * @param tokenName Name used for issued pool tokens * @param tokenSymbol Symbol used for issued pool tokens */ function initialize( PoolAddressListFlex memory poolAddressListFlex, IPoolConfigurableSettingsFlex memory poolSettings, string memory tokenName, string memory tokenSymbol ) public initializer { __ERC20_init(tokenName, tokenSymbol); _serviceConfiguration = IServiceConfigurationV3( poolAddressListFlex.serviceConfiguration ); _poolType = IPoolType.FlexRatePool; if ( poolSettings.dailyOriginationFeeRate > 1e18 || poolSettings.originationFee > 100000 || poolSettings.maxCapacity < 1e6 || poolSettings.maxCapacity > 1e24 || poolSettings.borrowerManagerAddr == address(0) || poolSettings.borrowerWalletAddr == address(0) || poolSettings.closeOfDepositTime > 1 days || poolSettings.closeOfWithdrawTime > 1 days || poolSettings.transferInDays > 5 || poolSettings.transferOutDays > 5 ) { revert InvalidPoolSetting(); } poolSettings.dailyOriginationFeeRate = PoolLibFlex.annualAPRToDailyRate( poolSettings.originationFee, ((poolSettings.originationFee * 1e18) / 1e4 / 400) ); if (!_serviceConfiguration.isPoolAdmin(poolAddressListFlex.poolAdmin)) { revert InvalidAccess(); } _liquidityAsset = IERC20Upgradeable(poolAddressListFlex.liquidityAsset); // Build the withdraw controller // Build the admin controller poolController = IPoolControllerFlex( IPoolControllerFactoryFlex( poolAddressListFlex.poolControllerFactoryFlex ).createController( address(this), poolAddressListFlex.serviceConfiguration, poolAddressListFlex.poolAdmin, poolAddressListFlex.liquidityAsset, poolSettings ) ); poolAccessControl = IPoolAccessControl( IPoolAccessControlFactory( poolAddressListFlex.poolAccessControlFactory ).create(address(this)) ); IBusinessDayRegistry _businessDayRegistry = IBusinessDayRegistry( IBusinessDayRegistryFactory( poolAddressListFlex.businessDayRegistryFactory ).create(address(this)) ); businessDayRegistry = _businessDayRegistry; uint256 lastDayAccrued; if (block.timestamp % 1 days < poolController.closeOfDepositTime()) { lastDayAccrued = _businessDayRegistry.toMidnight( uint64(block.timestamp) - 1 days ); } else { lastDayAccrued = _businessDayRegistry.toMidnight( uint64(block.timestamp) ); } _accountings = IPoolAccountingsFlex({ interestRate: 0, dailyInterestRate: 0, totalPrincipalEarningInterest: 0, totalInterestAccrued: 0, totalAssetsDeposited: 0, totalAssetsWithdrawn: 0, exchangeRate: 1e18, lastDayAccrued: lastDayAccrued, totalFees: 0, feesOutstanding: 0, interstRateSetTime: 0 }); withdrawDepositController = IWithdrawDepositControllerFlex( IWithdrawDepositControllerFactoryFlex( poolAddressListFlex.withdrawDepositControllerFactoryFlex ).createController( address(this), address(poolAddressListFlex.vaultFactory), address(poolSettings.borrowerWalletAddr) ) ); // Allow the contract to move infinite amount of vault liquidity assets _liquidityAsset.safeApprove(address(this), type(uint256).max); emit PoolCreated(); } /** * @inheritdoc IPoolBase */ function serviceConfiguration() public view returns (IServiceConfigurationV3) { return _serviceConfiguration; } function poolType() external view returns (IPoolType) { return _poolType; } /** * @inheritdoc IPoolFlex */ function settings() public view returns (IPoolConfigurableSettingsFlex memory poolSettings) { return poolController.settings(); } function nonBusinessDays() public view returns (uint64[] memory) { return businessDayRegistry.nonBusinessDays(); } function updateNonBusinessDays( uint64[] memory _timestamps ) external onlyPoolAdmin { updatePoolData(); return businessDayRegistry.updateNonBusinessDays(_timestamps); } function state() public view returns (IPoolLifeCycleStateFlex) { return poolController.state(); } /** * @inheritdoc IPoolBase */ function admin() external view override returns (address) { return poolController.admin(); } function borrowerManagerAddr() external view override returns (address) { return poolController.borrowerManagerAddr(); } function borrowerWalletAddr() external view override returns (address) { return poolController.borrowerWalletAddr(); } function transferInDays() external view returns (uint256) { return poolController.transferInDays(); } function transferOutDays() external view returns (uint256) { return poolController.transferOutDays(); } /** * @inheritdoc IPoolFlex */ function onActivated() external onlyPoolController { updatePoolData(); activatedAt = block.timestamp; } /** * @inheritdoc IPoolFlex */ function accountings() external view override returns (IPoolAccountingsFlex memory) { return _accountings; } /** * @inheritdoc IPoolFlex */ function totalAvailableAssets() public view returns (uint256 assets) { return _accountings.totalPrincipalEarningInterest + withdrawDepositController.totalAssetsTransitioningIn(); } function interestRate() public view override returns (uint256 assets) { return _accountings.interestRate; } function annualAPRToDailyRate( uint256 annualAPR, uint256 estimatedDailyRate ) external pure returns (uint256 _dailyInterestRate) { return PoolLibFlex.annualAPRToDailyRate(annualAPR, estimatedDailyRate); } function setDailyInterestRate( uint256 _interestRate, uint256 _estimatedDailyRate ) public onlyBorrowerManger { uint256 _dailyInterestRate = PoolLibFlex.annualAPRToDailyRate( _interestRate, _estimatedDailyRate ); _accountings.dailyInterestRate = _dailyInterestRate; _accountings.interestRate = _interestRate; _accountings.interstRateSetTime = block.timestamp; updatePoolData(); } function dailyInterestAccural() public onlyAutomationOrAdmin { uint256 midnight = uint256( block.timestamp - (block.timestamp % 1 days) ); if (block.timestamp % 1 days < poolController.closeOfDepositTime()) { midnight = midnight - 1 days; } if (midnight <= _accountings.lastDayAccrued) { revert AccuralCalledTooEarly(midnight, _accountings.lastDayAccrued); } uint256 numberOfDaysToAccrue = (midnight - _accountings.lastDayAccrued) / 1 days; uint256 currentDay = _accountings.lastDayAccrued; for (uint256 i = 0; i < numberOfDaysToAccrue; i++) { currentDay = currentDay + 1 days; _accountings.exchangeRate = _accountings .exchangeRate .mul(_accountings.dailyInterestRate + 1e18) .div(1e18); uint256 todaysInterest = (_accountings .totalPrincipalEarningInterest * (_accountings.dailyInterestRate)) / 1e18; uint256 todaysFees = (_accountings.totalPrincipalEarningInterest * (poolController.dailyOriginationFeeRate())) / 1e18; _accountings.totalPrincipalEarningInterest += todaysInterest; _accountings.totalInterestAccrued += todaysInterest; _accountings.totalFees += todaysFees; _accountings.feesOutstanding += todaysFees; uint256 inflows = withdrawDepositController.dailyInterestAccural( currentDay ); _accountings.totalPrincipalEarningInterest += inflows; } uint256 newlastDayAccrued = uint256( block.timestamp - (block.timestamp % 1 days) ); if (block.timestamp % 1 days < poolController.closeOfDepositTime()) { newlastDayAccrued = newlastDayAccrued - 1 days; } _accountings.lastDayAccrued = newlastDayAccrued; updatePoolData(); } function feesPaidDown(uint256 paidAmount) public onlyPoolAdmin { if (paidAmount > _accountings.feesOutstanding) { revert ExcessFeePayment(); } _accountings.feesOutstanding -= paidAmount; updatePoolData(); } function applyDailyRate(uint256 principal) public view returns (uint256) { return (principal * (1e18 + _accountings.dailyInterestRate)) / 1e18; } /** * @inheritdoc IPoolFlex */ function totalAvailableSupply() public view override returns (uint256 shares) { return totalSupply() - withdrawDepositController.totalSharesTransitioningIn() - withdrawDepositController.totalRequestedShares(); } /** * @inheritdoc IPoolBase */ function liquidityPoolAssets() public view returns (uint256 assets) { return _accountings.totalPrincipalEarningInterest + withdrawDepositController.totalAssetsTransitioningIn(); } /** * @inheritdoc IRequestWithdrawable */ function previewRedeemRequest( uint256 shares ) external view returns (uint256 assets) { assets = convertToAssets(shares); } /** * @inheritdoc IRequestWithdrawable */ function previewWithdrawRequest( uint256 assets ) external view returns (uint256 shares) { shares = convertToShares(assets); } /** * @inheritdoc IRequestWithdrawable */ function requestRedeem( uint256 shares ) external onlyNotPaused onlyActivatedPool onlyPermittedLender onlyLenderWithPPT returns (uint256 assets) { assets = convertToAssets(shares); if (assets > _accountings.totalPrincipalEarningInterest) { assets = _accountings.totalPrincipalEarningInterest; } withdrawDepositController.performRequest(msg.sender, shares, assets); _accountings.totalPrincipalEarningInterest -= assets; updatePoolData(); emit RedeemRequested(msg.sender, assets, shares); } /** * @inheritdoc IRequestWithdrawable */ function maxRedeemRequest( address owner ) public view returns (uint256 maxShares) { maxShares = withdrawDepositController.maxRedeemRequest(owner); } /** * @inheritdoc IRequestWithdrawable */ function maxWithdrawRequest( address owner ) public view returns (uint256 maxAssets) { maxAssets = convertToAssets(maxRedeemRequest(owner)); } function exchangeRate() public view override returns (uint256 _exchangeRate) { _exchangeRate = _accountings.exchangeRate; } /*////////////////////////////////////////////////////////////// ERC-4626 Methods //////////////////////////////////////////////////////////////*/ function liquidityAssetAddr() public view returns (address) { return address(_liquidityAsset); } function totalAssets() public view returns (uint256) { return _accountings.totalPrincipalEarningInterest + withdrawDepositController.totalAssetsTransitioningIn(); } function convertToShares( uint256 assets ) public view override returns (uint256 shares) { return (assets * 1e18) / exchangeRate(); } function convertToAssets( uint256 shares ) public view override returns (uint256 assets) { return shares.mul(exchangeRate()).div(1e18); } function closeOfDepositTime() external view returns (uint256) { return poolController.closeOfDepositTime(); } function closeOfWithdrawTime() external view returns (uint256) { return poolController.closeOfWithdrawTime(); } function getPoolConfiguration() external view returns (IPoolConfigurationStateFlex memory) { return PoolLibFlex.getPoolFlexConfigurationState(address(this)); } function getPoolOverview() external view returns (IPoolOverviewStateFlex memory) { return PoolLibFlex.getPoolFlexOverviewState(address(this)); } function getPoolAccountState( address accountAddr ) external view returns (IPoolAccountStateFlex memory) { IPoolAccountStateFlex memory ret = PoolLibFlex.getPoolAccountState( address(this), accountAddr ); return ret; } function maxDeposit(address owner) public view override returns (uint256) { if ( _serviceConfiguration.paused() == true || !isPermittedLender(owner) || poolController.state() != IPoolLifeCycleStateFlex.Active ) { return 0; } return 1e18; } function topOffSharesDueToExchangeRateDecrease( address lender, uint256 catchupShares ) external onlyWithdrawController { _mint(lender, catchupShares); } function deposit( uint256 assets, address lender ) public override onlyNotPaused atState(IPoolLifeCycleStateFlex.Active) onlyPermittedLender returns (uint256 shares, uint256 transferInDayTimestamp) { if ( poolController.state() == IPoolLifeCycleStateFlex.DisruptionOrDefault || msg.sender != lender ) revert PoolInvalidState(); if (assets > maxDeposit(lender)) { revert ExceedsMaxDeposit(maxDeposit(lender), assets, lender); } if (assets == 0) { revert ZeroDeposit(maxDeposit(lender), assets, lender); } uint256 inflows; (inflows, shares, transferInDayTimestamp) = withdrawDepositController .deposit( lender, assets, _accountings.exchangeRate, _accountings.dailyInterestRate ); _accountings.totalAssetsDeposited += assets; _liquidityAsset.safeTransferFrom(msg.sender, address(this), assets); _mint(lender, shares); _liquidityAsset.safeTransferFrom( address(this), borrowerVaultAddr(), assets ); withdrawDepositController.drawDownToBorrowerWallet(assets); _accountings.totalPrincipalEarningInterest += inflows; emit PoolDeposit(lender, assets, shares, transferInDayTimestamp); } /** * @dev Redeem a number of shares for a given number of assets. This method * will transfer `assets` from the vault to the `receiver`, and burn `shares` * from `owner`. */ function _performWithdrawTransfer( address owner, uint256 shares, uint256 assets ) internal { // Transfer assets _liquidityAsset.safeTransferFrom(address(this), owner, assets); // Burn the shares _burn(owner, shares); emit Withdraw(owner, owner, owner, assets, shares); updatePoolData(); } /*////////////////////////////////////////////////////////////// ERC-20 Overrides //////////////////////////////////////////////////////////////*/ /** * @dev Disables Perimeter Pool Token transfers. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override { super._beforeTokenTransfer(from, to, amount); if (to != address(0) && from != address(0)) { if ( !poolAccessControl.isAllowed(from) || !poolAccessControl.isAllowed(to) ) { revert TransferDisabled(); } if (maxRedeemRequest(from) < amount) { revert TransferDisabled(); } } if (from != address(0) && to != address(0)) { uint256 assetAmount = convertToAssets(amount); withdrawDepositController.tokenTransfer(from, to, assetAmount); } } function totalAssetsDueForWithdraws() public view returns (uint256) { return withdrawDepositController.totalAssetsDueForWithdraws(); } function borrowerVaultAddr() public view override returns (address) { return withdrawDepositController.borrowerVaultAddr(); } function withdrawEvents() public view returns (IPoolLenderWithdrawEvent[] memory) { return withdrawDepositController.withdrawEvents(); } function releaseWithdrawal( uint256 eventId ) public onlyPoolAdmin returns (IPoolLenderWithdrawEvent memory ev) { ev = withdrawDepositController.releaseWithdrawal(eventId); emit RepayLoanToLender( ev.lender, eventId, ev.requestedShares, ev.requestedAssets ); _performWithdrawTransfer( ev.lender, ev.requestedShares, ev.requestedAssets ); _accountings.totalAssetsWithdrawn += ev.requestedAssets; updatePoolData(); } function repayLoans( uint256 assets, uint256 eventId ) public onlyBorrowerManger { IPoolLenderWithdrawEvent[] memory _withdrawEvents = withdrawDepositController.withdrawEvents(); IPoolLenderWithdrawEvent memory ev; bool isFound = false; for (uint i = 0; i < _withdrawEvents.length; i++) { if (_withdrawEvents[i].eventId == eventId) { ev = _withdrawEvents[i]; isFound = true; } } if (!isFound || ev.requestedAssets > assets) { revert InvalidRepayment(); } withdrawDepositController.repayLoans(assets); emit RepayToPoolProcessed( ev.lender, eventId, ev.requestedShares, ev.requestedAssets ); updatePoolData(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../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 Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; 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. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * 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 prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20Upgradeable.sol"; import "./extensions/IERC20MetadataUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @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[45] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20MetadataUpgradeable is IERC20Upgradeable { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20PermitUpgradeable { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; import "../extensions/IERC20PermitUpgradeable.sol"; import "../../../utils/AddressUpgradeable.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20Upgradeable { using AddressUpgradeable for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20PermitUpgradeable token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @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; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "../../interfaces/IPool.sol"; import "../../interfaces/ILoan.sol"; /** * @dev Expresses the various states a pool can be in throughout its lifecycle. */ enum IPoolLifeCycleState { Initialized, Active, Closed, DisruptionOrDefault } /** * @title The various configurable settings that customize Pool behavior. */ struct IPoolConfigurableSettings { uint256 maxCapacity; // amount uint256 endDate; // epoch seconds address borrowerManager; address borrowerWalletAddress; uint256 closeOfBusinessTime; uint256 earlyWithdrawFeeBps; } /** * @title A Pool's Admin controller * @dev Pool Admin's interact with the pool via the controller, including funding loans and adjusting * settings. */ interface IPoolController { /** * @dev Emitted when pool settings are updated. */ event PoolSettingsUpdated(); /** * @dev Emitted when the pool transitions a lifecycle state. */ event LifeCycleStateTransition(IPoolLifeCycleState state); /** * @dev Emitted when a pool is marked as in DisruptionOrDefault. */ event DisruptionOrDefault(address indexed pool); event Rescheduled(address indexed pool); function version() external returns (uint16); /** * @dev The Pool's admin */ function admin() external view returns (address); /*////////////////////////////////////////////////////////////// Settings //////////////////////////////////////////////////////////////*/ /** * @dev The current configurable pool settings. */ function settings() external view returns (IPoolConfigurableSettings memory); function serviceConfiguration() external view returns (address); /** * @dev Allow the current pool admin to update the pool capacity at any * time. */ function setPoolCapacity(uint256) external; /** * @dev Allow the current pool admin to update the pool's end date. The end date can * only be moved earlier (but not in the past, as measured by the current block's timestamp). * Once the end date is reached, the Pool is closed. */ function setPoolEndDate(uint256) external; function closeOfBusinessTime() external view returns (uint256); function borrowerManager() external view returns (address); function borrowerWalletAddress() external view returns (address); /*////////////////////////////////////////////////////////////// State //////////////////////////////////////////////////////////////*/ function reschedule( address loan, uint256 accrualStartDayTimestamp, uint256 transferInWindowDurationDays, uint256 transferOutWindowDurationDays, uint256 durationDays ) external; /** * @dev Returns the current pool lifecycle state. */ function state() external view returns (IPoolLifeCycleState); function activatePool() external; /*////////////////////////////////////////////////////////////// Loans //////////////////////////////////////////////////////////////*/ function approveLoanForPool(address loan) external; function initiateRollover(address loan, address priorLoan) external; function completeRolloverNetPayment(address) external; function disruptionOrDefault() external; function releaseRolloverRedemption(address owner) external; /*////////////////////////////////////////////////////////////// Fees //////////////////////////////////////////////////////////////*/ /** * @dev Called by the pool admin, this claims fees that have accumulated * in the Pool's FeeVault from ongoing borrower payments. */ function withdrawFeeVault(uint256 amount, address receiver) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "../../interfaces/IPool.sol"; import "../../interfaces/ILoan.sol"; /** * @dev Expresses the various states a pool can be in throughout its lifecycle. */ enum IPoolLifeCycleStateFlex { Initialized, Active, Closed, DisruptionOrDefault } /** * @title The various configurable settings that customize Pool behavior. */ struct IPoolConfigurableSettingsFlex { uint256 maxCapacity; // amount address borrowerManagerAddr; address borrowerWalletAddr; uint256 closeOfDepositTime; uint256 closeOfWithdrawTime; uint256 originationFee; uint256 dailyOriginationFeeRate; uint256 transferInDays; uint256 transferOutDays; } /** * @title A Pool's Admin controller * @dev Pool Admin's interact with the pool via the controller, including funding loans and adjusting * settings. */ interface IPoolControllerFlex { /** * @dev Emitted when pool settings are updated. */ event PoolSettingsUpdated(); /** * @dev Emitted when the pool transitions a lifecycle state. */ event LifeCycleStateTransition(IPoolLifeCycleStateFlex state); /** * @dev Emitted when a pool is marked as in DisruptionOrDefault. */ event DisruptionOrDefault(address indexed pool); event Rescheduled(address indexed pool); function version() external returns (uint16); /** * @dev The Pool's admin */ function admin() external view returns (address); /*////////////////////////////////////////////////////////////// Settings //////////////////////////////////////////////////////////////*/ /** * @dev The current configurable pool settings. */ function settings() external view returns (IPoolConfigurableSettingsFlex memory); function serviceConfiguration() external view returns (address); /** * @dev Allow the current pool admin to update the pool capacity at any * time. */ function updatePoolSettings( IPoolConfigurableSettingsFlex memory poolSettings_ ) external; function dailyOriginationFeeRate() external view returns (uint256); function originationFee() external view returns (uint256); function closeOfDepositTime() external view returns (uint256); function closeOfWithdrawTime() external view returns (uint256); function transferInDays() external view returns (uint256); function transferOutDays() external view returns (uint256); function borrowerManagerAddr() external view returns (address); function borrowerWalletAddr() external view returns (address); function disruptionOrDefault() external; /** * @dev Returns the current pool lifecycle state. */ function state() external view returns (IPoolLifeCycleStateFlex); function activatePool() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "../../interfaces/IPool.sol"; struct IPoolRolloverWithdrawState { uint256 requestedShares; // Number of shares requested in the `latestPeriod` uint256 requestedAssets; uint256 redeemableShares; // The shares that are currently withdrawable uint256 withdrawableAssets; // The assets that are currently withdrawable uint256 earlyRequestedShares; // The period in which the shares were requested uint256 earlyRequestedAssets; uint256 earlyAcceptedShares; // The period in which the shares were requested uint256 earlyAcceptedAssets; } /** * @title A Pool's Withdraw controller * @dev Holds state related to withdraw requests, and logic for snapshotting the * pool's liquidity reserve at regular intervals, earmarking funds for lenders according * to their withdrawal requests. */ interface IWithdrawController { function version() external pure returns (uint16); function pool() external view returns (address); function feeVault() external view returns (address); function borrowerVault() external view returns (address); function borrowerWallet() external view returns (address); function withdrawFeeVault(uint256 amount, address receiver) external; /*////////////////////////////////////////////////////////////// Balance Views //////////////////////////////////////////////////////////////*/ function drawDownToBorrowerWallet(uint256 amount) external; function redemptionState() external view returns (IRedemptionState memory); function requestedSharesOf( address owner ) external view returns (uint256 shares); function requestedAssetsOf( address owner ) external view returns (uint256 assets); function redeemableSharesOf( address owner ) external view returns (uint256 shares); function withdrawableAssetsOf( address owner ) external view returns (uint256 assets); /** * @dev Returns the number of shares that are available to be redeemed by * the owner in the current block. */ function totalRequestedShares() external view returns (uint256); function totalRequestedAssets() external view returns (uint256 assets); /** * @dev Returns the number of shares that are available to be redeemed * overall in the current block. */ function totalRedeemableShares() external view returns (uint256); /** * @dev Returns the number of `assets` that are available to be withdrawn * overall in the current block. */ function totalWithdrawableAssets() external view returns (uint256); function releaseRolloverRedemption( address owner ) external returns (uint256 shares, uint256 assets); /*////////////////////////////////////////////////////////////// Max Methods //////////////////////////////////////////////////////////////*/ /** * @dev Returns the maximum number of `shares` that can be * requested to be redeemed from the owner balance with a single * `requestRedeem` call in the current block. * * Note: This is equivalent of EIP-4626 `maxRedeem` */ function maxRedeemRequest(address) external view returns (uint256); /** * @dev The maximum amount of shares that can be redeemed from the owner * balance through a redeem call. */ function maxRedeem(address) external view returns (uint256); /** * @dev Returns the maximum amount of underlying assets that can be * withdrawn from the owner balance with a single withdraw call. */ function maxWithdraw(address) external view returns (uint256); /*////////////////////////////////////////////////////////////// Preview Methods //////////////////////////////////////////////////////////////*/ /** * @dev Simulates the effects of their redeemption at the current block. * Per EIP4626, should round DOWN. */ function previewRedeem(address, uint256) external view returns (uint256); /** * @dev Simulate the effects of their withdrawal at the current block. * Per EIP4626, should round UP on the number of shares required for assets. */ function previewWithdraw(address, uint256) external view returns (uint256); /*////////////////////////////////////////////////////////////// Request Methods //////////////////////////////////////////////////////////////*/ /** * @dev Requests redeeming a specific number of `shares` and `assets` from * the pool. * * NOTE: The pool is responsible for handling any fees, and for providing * the proper shares/assets ratio. */ function performRequest(address, uint256, uint256) external; /*////////////////////////////////////////////////////////////// Early Withdraw Methods //////////////////////////////////////////////////////////////*/ function requestEarlyRedeem( address owner, uint256 shares ) external returns (uint256 principal); function acceptEarlyRedeemRequest( address investorAddr ) external returns (uint256 shares, uint256 principal); function repayEarlyWithdraw( address investorAddr, uint256 amount ) external returns ( uint256 principal, uint256 repayment, uint256 redeemedShares, uint256 fees, uint256 assetReduction ); function totalEarlyRequestedShares() external view returns (uint256 shares); function totalEarlyRequestedAssets() external view returns (uint256 assets); function totalEarlyAcceptedShares() external view returns (uint256 shares); function totalEarlyAcceptedAssets() external view returns (uint256 assets); function earlyRequestedSharesOf( address owner ) external view returns (uint256 shares); function earlyRequestedAssetsOf( address owner ) external view returns (uint256 assets); function earlyAcceptedSharesOf( address owner ) external view returns (uint256 shares); function earlyAcceptedAssetsOf( address owner ) external view returns (uint256 assets); /*////////////////////////////////////////////////////////////// Withdraw / Redeem //////////////////////////////////////////////////////////////*/ /** * @dev Redeems a specific number of shares from owner and send assets of underlying token from the vault to receiver. * * Per EIP4626, should round DOWN. */ function redeem(address, uint256) external returns (uint256); /** * @dev Burns shares from owner and send exactly assets token from the vault to receiver. * Should round UP for EIP4626. */ function withdraw(address, uint256) external returns (uint256); function payFees(uint256) external; function repayLoan(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "../../interfaces/IPoolFlex.sol"; struct IPoolLenderWithdrawEvent { uint256 requestedShares; // Number of shares requested in the `latestPeriod` uint256 requestedAssets; uint256 transferOutDayTimestamp; uint256 requestTimestamp; address lender; uint256 eventId; } struct IPoolLenderTotals { uint256 requestedShares; // Number of shares requested in the `latestPeriod` uint256 requestedAssets; address lender; uint256 assetsDeposited; uint256 assetsWithdrawn; uint256 sharesTransitioningIn; uint256 assetsTransitioningIn; uint256 assetsDueForWithdraws; uint256 sharesDueForWithdraws; } struct IDailyWithdrawTotals { uint256 requestedShares; // Number of shares requested in the `latestPeriod` uint256 requestedAssets; uint256 transferOutDayTimestamp; } struct IPoolWithdrawTotal { uint256 requestedShares; // Number of shares requested in the `latestPeriod` uint256 requestedAssets; } struct IPoolLenderDepositEvent { uint256 mintedShares; uint256 depositedAssets; uint256 transferInDayTimestamp; address lender; } struct IDailyDepositTotals { uint256 mintedShares; uint256 depositedAssets; uint256 transferInDayTimestamp; } struct IPoolDepositsTotal { uint256 mintedShares; uint256 depositedAssets; } /** * @title A Pool's Withdraw controller * @dev Holds state related to withdraw requests, and logic for snapshotting the * pool's liquidity reserve at regular intervals, earmarking funds for lenders according * to their withdrawal requests. */ interface IWithdrawDepositControllerFlex { function version() external pure returns (uint16); function poolAddr() external view returns (address); function pool() external view returns (address); // back compatible function feeVaultAddr() external view returns (address); function borrowerVaultAddr() external view returns (address); function lenderTotals( address lender ) external view returns (IPoolLenderTotals memory); function borrowerVault() external view returns (address); // back compatible function borrowerWallet() external view returns (address); function borrowerWalletAddr() external view returns (address); function dailyInterestAccural( uint256 currentDay ) external returns (uint256 inflows); function deposit( address lender, uint256 assets, uint256 exchangeRate, uint256 interestRate ) external returns ( uint256 inflows, uint256 shares, uint256 transferInDayTimestamp ); /*////////////////////////////////////////////////////////////// Balance Views //////////////////////////////////////////////////////////////*/ function drawDownToBorrowerWallet(uint256 amount) external; function requestedSharesOf( address owner ) external view returns (uint256 shares); function requestedAssetsOf( address owner ) external view returns (uint256 assets); function totalAssetsTransitioningIn() external view returns (uint256 assets); function totalSharesTransitioningIn() external view returns (uint256 shares); /** * @dev Returns the number of shares that are available to be redeemed by * the owner in the current block. */ function totalRequestedShares() external view returns (uint256 shares); function totalRequestedAssets() external view returns (uint256 assets); /*////////////////////////////////////////////////////////////// Max Methods //////////////////////////////////////////////////////////////*/ /** * @dev Returns the maximum number of `shares` that can be * requested to be redeemed from the owner balance with a single * `requestRedeem` call in the current block. * * Note: This is equivalent of EIP-4626 `maxRedeem` */ function maxRedeemRequest(address) external view returns (uint256); /*////////////////////////////////////////////////////////////// Request Methods //////////////////////////////////////////////////////////////*/ /** * @dev Requests redeeming a specific number of `shares` and `assets` from * the pool. * * NOTE: The pool is responsible for handling any fees, and for providing * the proper shares/assets ratio. */ function performRequest(address, uint256, uint256) external; /*////////////////////////////////////////////////////////////// Withdraw / Redeem //////////////////////////////////////////////////////////////*/ function totalAssetsDueForWithdraws() external view returns (uint256); function releaseWithdrawal( uint256 eventId ) external returns (IPoolLenderWithdrawEvent memory ev); function withdrawEvents() external view returns (IPoolLenderWithdrawEvent[] memory); function repayLoans(uint256 assets) external; function tokenTransfer( address from, address to, uint256 assetAmount ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title An interface for a factory that creates BusinessDayRegistry contracts. */ interface IBusinessDayRegistryFactory { /** * @dev Creates a new BusinessDayRegistry */ function create(address pool) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title An interface for a factory that creates PoolAccessControl contracts. */ interface IPoolAccessControlFactory { /** * @dev Creates a new PoolAccessControl. */ function create(address pool) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "../../interfaces/IPoolFlex.sol"; /** * @title Interface for the PoolController factory. */ interface IPoolControllerFactoryFlex { /** * @dev Emitted when a pool is created. */ event PoolControllerCreated(address indexed pool, address indexed addr); /** * @dev Creates a pool's PoolAdmin controller * @dev Emits `PoolControllerCreated` event. */ function createController( address pool, address serviceConfiguration, address admin, address liquidityAsset, IPoolConfigurableSettingsFlex memory poolSettings ) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title Interface for the VaultFactory. */ enum IVaultType { Default, PoolVault, BorrowerVault, FeeVault, FundingVault } interface IVaultFactory { /** * @dev Emitted when a vault is created. */ event VaultCreated(address indexed owner); /** * @dev Creates a new vault. * @dev Emits a `VaultCreated` event. */ function createVault( address owner, IVaultType vaultType ) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title Interface for the WithdrawDepositControllerFlex factory. */ interface IWithdrawDepositControllerFactoryFlex { /** * @dev Emitted when a pool WithdrawController is created. */ event WithdrawDepositControllerCreated(address indexed addr); /** * @dev Creates a pool's withdraw controller * @dev Emits `WithdrawDepositControllerCreated` event. */ function createController( address pool, address vaultFactory, address borrowerWalletAddress ) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title The interface for interacting with IBusinessDayRegistry */ interface IBusinessDayRegistry { event AddHoliday(uint256 _timestamp); function isBusinessDay(uint64 _timestamp) external view returns (bool); function isHoliday(uint64 _timestamp) external view returns (bool); function isWeekDay(uint64 _timestamp) external pure returns (bool); function addHoliday(uint64 _timestamp) external; function toMidnight(uint64 _timestamp) external pure returns (uint64); function nonBusinessDays() external view returns (uint64[] memory); function updateNonBusinessDays(uint64[] memory _timestamps) external; function businessDaysToCalendarDays( uint64 _timestamp, uint256 depositCutoffTime, uint256 transferBusinessDays ) external view returns (uint8 numberOfDays, uint256 transferDayTimestamp); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; /** * @title The interface according to the ERC-4626 standard. */ interface IERC4626 is IERC20Upgradeable { /** * @dev Emitted when tokens are deposited into the vault via the mint and deposit methods. */ event Deposit( address indexed sender, address indexed owner, uint256 assets, uint256 shares ); /** * @dev Emitted when shares are withdrawn from the vault by a depositor in the redeem or withdraw methods. */ event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /** * @dev Return the address of the underlying ERC-20 token used for the vault for accounting, depositing, withdrawing. */ function asset() external view returns (address); /** * @dev Calculate the total amount of underlying assets held by the vault. * NOTE: This method includes assets that are marked for withdrawal. */ function totalAssets() external view returns (uint256); /** * @dev Calculates the amount of shares that would be exchanged by the vault for the amount of assets provided. * Rounds DOWN per EIP4626. */ function convertToShares(uint256 assets) external view returns (uint256); /** * @dev Calculates the amount of assets that would be exchanged by the vault for the amount of shares provided. * Rounds DOWN per EIP4626. */ function convertToAssets(uint256 shares) external view returns (uint256); /** * @dev Calculates the maximum amount of underlying assets that can be deposited in a single deposit call by the receiver. */ function maxDeposit(address receiver) external view returns (uint256); /** * @dev Allows users to simulate the effects of their deposit at the current block. */ function previewDeposit(uint256 assets) external view returns (uint256); /** * @dev Deposits assets of underlying tokens into the vault and grants ownership of shares to receiver. * Emits a {Deposit} event. */ function deposit( uint256 assets, address receiver ) external returns (uint256); /** * @dev Returns the maximum amount of shares that can be minted in a single mint call by the receiver. */ function maxMint(address receiver) external view returns (uint256); /** * @dev Allows users to simulate the effects of their mint at the current block. */ function previewMint(uint256 shares) external view returns (uint256); /** * @dev Mints exactly shares vault shares to receiver by depositing assets of underlying tokens. * Emits a {Deposit} event. */ function mint(uint256 shares, address receiver) external returns (uint256); /** * @dev Returns the maximum amount of underlying assets that can be withdrawn from the owner balance with a single withdraw call. */ function maxWithdraw(address owner) external view returns (uint256); /** * @dev Simulate the effects of their withdrawal at the current block. * Per EIP4626, should round UP on the number of shares required for assets. */ function previewWithdraw(uint256 assets) external view returns (uint256); /** * @dev Burns shares from owner and send exactly assets token from the vault to receiver. * Emits a {Withdraw} event. * Should round UP for EIP4626. */ function withdraw( uint256 assets, address receiver, address owner ) external returns (uint256); /** * @dev The maximum amount of shares that can be redeemed from the owner balance through a redeem call. */ function maxRedeem(address owner) external view returns (uint256); /** * @dev Simulates the effects of their redeemption at the current block. * Per EIP4626, should round DOWN. */ function previewRedeem(uint256 shares) external view returns (uint256); /** * @dev Redeems a specific number of shares from owner and send assets of underlying token from the vault to receiver. * Emits a {Withdraw} event. * Per EIP4626, should round DOWN. */ function redeem( uint256 shares, address receiver, address owner ) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "./IServiceConfigurationV3.sol"; import "../interfaces/IVault.sol"; /** * @title An enum capturing the various states a Loan may be in. */ enum ILoanLifeCycleState { Requested, Canceled, Funded, Matured, Active, Settled } enum ILoanTransitionState { Created /* RequestedLoan */, ApprovedForDeposits /* RequestedLoan */, TransitioningFundsIn /* RequestedLoan */, AccruingInterest /* ActiveLoan */, RedemptionsClosed /* ActiveLoan */, TransitioningFundsOut /* MaturedLoan */, RedemptionsReleased /* Settled loan */ } struct ILoanCompleteState { address loanAddr; address borrowerAddr; address fundingVaultAddr; address poolAddr; uint256 state; uint256 transitionState; uint256 durationDays; uint256 principal; uint256 startingPrincipal; uint256 interest; uint256 indicativeInterest; uint256 originationFee; uint256 indicativeApr; uint256 finalizedApr; uint256 exchangeRateAtDeposit; uint256 exchangeRateAtMaturity; uint256 fundingVaultBalance; uint256 assetsRolloverToNextLoan; uint256 assetsToReturnToPool; uint256 assetsFromPool; uint256 accrualStartDayTimestamp; uint256 accrualStartTimestamp; uint256 transferInWindowDurationDays; uint256 transferOutWindowDurationDays; uint256 depositClosingTimestamp; uint256 redemptionRequestClosingTimestamp; uint256 maturingTimestamp; uint256 redemptionAvailableTimestamp; ILoanRolloverAccounting rolloverAccounting; bool canRequestRedemption; } /** * @title The various Loan terms. */ struct ILoanSettings { uint256 principal; uint256 indicativeApr; uint256 finalizedApr; uint256 durationDays; uint256 dropDeadTimestamp; uint256 originationBps; uint256 accrualStartDayTimestamp; uint256 transferInWindowDurationDays; uint256 transferOutWindowDurationDays; address priorLoan; uint256 startingPrincipal; } struct ILoanRolloverAccounting { uint256 totalSupply; uint256 assetsFromPool; uint256 assetsFromPriorLoan; uint256 assetToReturnToPool; uint256 exchangeRateAtDeposit; uint256 exchangeRateAtMaturity; } /** * @title The primary interface for Perimeter loans. */ interface ILoan { /** * @dev Emitted when loan is funded. */ event LoanFunded(address asset, uint256 amount); /** * @dev Emitted when a Loan's lifecycle state transitions */ event LifeCycleStateTransition(ILoanLifeCycleState state); function getRolloverAccounting() external view returns (ILoanRolloverAccounting memory); function approve() external; function canRequestRedemption() external view returns (bool); function inDepositWindow() external view returns (bool); function inInitiateRolloverWindow() external view returns (bool); function exchangeRateAtDeposit() external view returns (uint256); function exchangeRateAtMaturity() external view returns (uint256); function assetsRolloverToNextLoan() external view returns (uint256); function assetsFromPool() external view returns (uint256); function assetsToReturnToPool() external view returns (uint256); function accrualStartTimestamp() external view returns (uint256); function accrualStartDayTimestamp() external view returns (uint256); function transferInWindowDurationDays() external view returns (uint256); function transferOutWindowDurationDays() external view returns (uint256); function depositClosingTimestamp() external view returns (uint256); function earlyRedeemRequestClosingTimestamp() external view returns (uint256); function redemptionRequestClosingTimestamp() external view returns (uint256); function maturingTimestamp() external view returns (uint256); function redemptionAvailableTimestamp() external view returns (uint256); /** * @dev Current Loan lifecycle state. */ function state() external view returns (ILoanLifeCycleState); function transitionState() external view returns (ILoanTransitionState); /** * @dev The loan's borrower. */ function borrower() external view returns (address); /** * @dev The pool associated with a loan. */ function pool() external view returns (address); /** * @dev The factory that created the loan. */ function factory() external view returns (address); /** * @dev A timestamp that controls when the loan can be dissolved */ function dropDeadTimestamp() external view returns (uint256); /** * @dev Amount expected in each payment */ function interest() external view returns (uint256); function indicativeInterest() external view returns (uint256); function rolloverMaturedLoan() external; function rolloverAndFinalizeApr(uint256 apr) external; function rolloverAllocation( uint256 assetsRolloverToNextLoan_, uint256 assetToReturnToPool_ ) external; function completeRolloverNetPayment() external returns ( uint256 feeVaultAmount, uint256 assetsReturnedToPool, uint256 interestAccrued ); function fundRollover( uint256 assetsFromPool, uint256 assetsFromPriorLoan, uint256 totalSupply, address priorLoan ) external returns (ILoanLifeCycleState); function reschedule( uint256 accrualStartDayTimestamp_, uint256 transferInWindowDurationDays_, uint256 transferOutWindowDurationDays_, uint256 durationDays_ ) external; /** * @dev When the loan was created. */ function createdAt() external returns (uint256); /** * @dev Duration of the loan, after which the principal must be returned. */ function durationDays() external view returns (uint256); /** * @dev Interest rate for the loan. */ function finalizedApr() external view returns (uint256); function indicativeApr() external view returns (uint256); function originationFee() external view returns (uint256); /** * @dev Amount of loan principal. */ function principal() external view returns (uint256); function startingPrincipal() external view returns (uint256); /** * @dev Address of the loan's funding vault, which holds liquidity transferred from the pool. */ function fundingVault() external view returns (IVault); /** * @dev Liquidity asset of the loan or pool. */ function liquidityAsset() external view returns (address); /** * @dev Address of the global service configuration. */ function serviceConfiguration() external view returns (IServiceConfigurationV3); function repayEarlyWithdraw( uint256 principal, uint256 assetReduction ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "./IERC4626.sol"; import "./IServiceConfiguration.sol"; import "../controllers/interfaces/IPoolController.sol"; import "./IPoolBase.sol"; import "../controllers/interfaces/IWithdrawController.sol"; import "./ILoan.sol"; import "../interfaces/IPoolAccessControl.sol"; /* Paired with rolloverTiming field */ enum IPoolRolloverState { EarlyRolloverInitiate, // 0 accept Deposits and WithdrawRequests, no early withdraws) transitionTiming = time to expected rollover */ RolloverInitiate, // 1 no deposits or withdrawRequests) transitionTiming = time left of expected rollover */ LateRolloverInitiate, // 2 transitionTiming = time expected rollover pastDue */ EarlyRolloverFinalize, // 3 Requested RolloverFinalize, // 4 Requested LateRolloverFinalize, // 5 Requested EarlyRepayWithdrawsAndFees, // 6 Matured loan RepayWithdrawsAndFees, // 7 Matured loan LateRepayWithdrawsAndFees, // 8 Matured loan EarlyReleaseRedemptions, // 9 Matured loan ReleaseRedemptions, // 10 Matured loan LateReleaseRedemptions, // 11 Matured loan CreateNextLoan, // 12 ApproveNextLoan, //13 LateApproveNextLoan, //14 LoanNeedsRescheduling, //15 NotRollingOver, //16 InvalidState // 17 } enum IPoolRolloverActor { PoolAdmin, // 0 BorrowerManager, //1 BorrowerWallet, //2 Investor // 3 } struct IPoolAccountings { uint256 totalAvailableAssets; uint256 outstandingLoanPrincipals; uint256 totalAssetsDeposited; uint256 totalAssetsWithdrawn; } struct IPoolRolloverStateStruct { IPoolRolloverState rolloverState; IPoolRolloverActor rolloverActor; uint256 rolloverTimeToActionWindow; uint256 rolloverTimeLeftInActionWindow; uint256 rolloverTimePastActionWindow; } struct IPoolConfigurationState { address poolAddr; address admin; address poolController; address feeVault; address withdrawController; string name; string symbol; address borrowerManager; address borrowerWallet; address borrowerVault; uint256 maxCapacity; uint256 closeOfBusinessTime; uint256 poolEndDate; address liquidityPoolAssetAddr; } struct IRedemptionState { address[] redemptionLenders; uint256[] requestedShares; uint256[] redeemableShares; } struct IPoolOverviewState { address poolAddr; address[] settledLoans; uint8 state; uint8 rolloverState; uint8 rolloverActor; uint256 rolloverTimeToActionWindow; uint256 rolloverTimeLeftInActionWindow; uint256 rolloverTimePastActionWindow; uint256 totalAvailableAssets; uint256 totalAvailableSupply; uint256 currentExpectedInterest; uint256 liquidityPoolAssets; uint256 totalAssets; uint256 totalOutstandingLoanPrincipal; uint256 totalAssetsDeposited; uint256 totalAssetsWithdrawn; uint256 totalRequestedShares; uint256 totalRedeemableShares; uint256 totalWithdrawableAssets; uint256 totalRequestedAssets; uint256 feeVaultBalance; uint256 borrowerVaultBalance; uint256 borrowerWalletBalance; uint256 poolBalance; uint256 exchangeRateAtMaturity; ILoanCompleteState requestedLoanState; ILoanCompleteState activeLoanState; ILoanCompleteState maturedLoanState; ILoanCompleteState createdLoanState; IRedemptionState redemptionState; uint256 totalEarlyRequestedShares; uint256 totalEarlyRequestedAssets; uint256 totalEarlyAcceptedShares; uint256 totalEarlyAcceptedAssets; } struct IPoolAccountState { address poolAddr; address accountAddr; uint256 balance; uint256 maxWithdrawRequest; uint256 maxRedeemRequest; uint256 maxWithdraw; uint256 maxRedeem; uint256 requestedSharesOf; uint256 redeemableSharesOf; uint256 requestedAssetsOf; uint256 withdrawableAssetsOf; uint256 earlyRequestedSharesOf; uint256 earlyRequestedAssetsOf; uint256 earlyAcceptedSharesOf; uint256 earlyAcceptedAssetsOf; } struct PoolAddressList { address liquidityAsset; address poolAdmin; address serviceConfiguration; address withdrawControllerFactory; address poolControllerFactory; address vaultFactory; address poolAccessControlFactory; } /** * @title The interface for liquidity pools. */ interface IPool is IPoolBase { event Deposit( address indexed sender, address indexed owner, uint256 assets, uint256 shares ); event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /** * @dev The PoolController contract */ function poolController() external view returns (IPoolController); /** * @dev The WithdrawController contract */ function withdrawController() external view returns (IWithdrawController); /** * @dev The current configurable pool settings. */ function settings() external view returns (IPoolConfigurableSettings calldata settings); /** * @dev The current pool state. */ function state() external view returns (IPoolLifeCycleState); /** * @dev The pool accounting variables; */ function accountings() external view returns (IPoolAccountings memory); function closeOfBusinessTime() external view returns (uint256); /** * @dev Callback from the pool controller when the pool is activated */ function onActivated() external; function initiateRollover(address loan, address priorLoan) external; function completeRolloverNetPayment(address) external; function withdrawFeeVault(uint256 amount, address receiver) external; function loanCreated(address loan) external; function reschedule( address loan, uint256 accrualStartDayTimestamp, uint256 transferInWindowDurationDays, uint256 transferOutWindowDurationDays, uint256 durationDays ) external; function redemptionState() external view returns (IRedemptionState memory _redemptionState); function releaseRolloverRedemption(address owner) external; function exchangeRateAtMaturity() external view returns (uint256 _exchangeRateAtMaturity); function exchangeRateAtDeposit() external view returns (uint256); /** * @dev Calculate the total amount of underlying assets held by the vault, * excluding any assets due for withdrawal. */ function totalAvailableAssets() external view returns (uint256); /** * @dev The total available supply that is not marked for withdrawal */ function totalAvailableSupply() external view returns (uint256); /** * @dev The accrued interest at the current block. */ function currentExpectedInterest() external view returns (uint256 interest); function rolloverAndFinalizeApr(uint256 _apr) external; /*////////////////////////////////////////////////////////////// LOAN SET OPERATIONS //////////////////////////////////////////////////////////////*/ function approveLoanForPool(address loan) external; function createdLoan() external view returns (address); function activeLoan() external view returns (address); function requestedLoan() external view returns (address); function maturedLoan() external view returns (address); function settledLoans() external view returns (address[] memory); /*////////////////////////////////////////////////////////////// Early Withdraw //////////////////////////////////////////////////////////////*/ function requestEarlyRedeem(uint256 shares) external; function acceptEarlyRedeemRequest( address investorAddr ) external returns (uint256 principal); function repayEarlyWithdraw( address investorAddr, uint256 amount ) external returns ( uint256 principal, uint256 repayment, uint256 redeemedShares, uint256 fees ); function deposit( uint256 assets, address lender ) external returns (uint256 shares); function convertToAssets( uint256 shares ) external view returns (uint256 assets); function convertToShares( uint256 assets ) external view returns (uint256 shares); function maxWithdraw(address owner) external view returns (uint256 assets); function maxRedeem(address owner) external view returns (uint256 maxShares); function totalAssets() external view returns (uint256); function asset() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title The interface for controlling access to Pools */ interface IPoolAccessControl { /** * @dev Check if an address is allowed as a participant in the pool * @param addr The address to verify * @return whether the address is allowed as a participant */ function isAllowed(address addr) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "./IRequestWithdrawable.sol"; import "./IServiceConfigurationV3.sol"; import "./IPoolAccessControl.sol"; import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; enum IPoolType { TermPool, FlexRatePool } interface IPoolBase is IERC20Upgradeable, IRequestWithdrawable { function poolType() external view returns (IPoolType); function liquidityAssetAddr() external view returns (address); function version() external view returns (uint16); /** * @dev The ServiceConfiguration. */ function serviceConfiguration() external view returns (IServiceConfigurationV3); /** * @dev The admin for the pool. */ function admin() external view returns (address); function borrowerManagerAddr() external view returns (address); function borrowerWalletAddr() external view returns (address); /** * @dev The activation timestamp of the pool. */ function activatedAt() external view returns (uint256); function poolAccessControl() external view returns (IPoolAccessControl); /** * @dev The sum of all assets available in the liquidity pool, excluding * any assets that are marked for withdrawal. */ function liquidityPoolAssets() external view returns (uint256); function isPermittedLender(address) external view returns (bool); function maxDeposit(address owner) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "./IERC4626.sol"; import "./IServiceConfigurationV3.sol"; import "./IRequestWithdrawable.sol"; import "../controllers/interfaces/IPoolControllerFlex.sol"; import "../controllers/interfaces/IWithdrawDepositControllerFlex.sol"; import "./IPoolBase.sol"; import "../interfaces/IPoolAccessControl.sol"; import "../interfaces/IBusinessDayRegistry.sol"; struct IPoolAccountingsFlex { uint256 interestRate; uint256 dailyInterestRate; uint256 totalPrincipalEarningInterest; uint256 totalInterestAccrued; uint256 totalAssetsDeposited; uint256 totalAssetsWithdrawn; uint256 exchangeRate; uint256 lastDayAccrued; uint256 totalFees; uint256 feesOutstanding; uint256 interstRateSetTime; } struct IPoolConfigurationStateFlex { address poolAddr; uint256 dailyOriginationFeeRate; uint256 originationFee; uint256 closeOfDepositTime; uint256 closeOfWithdrawTime; uint256 transferInDays; uint256 transferOutDays; address liquidityAssetAddr; address poolAdminAddr; address poolControllerAddr; address withdrawControllerAddr; address borrowerVaultAddr; string name; string symbol; address borrowerManagerAddr; address borrowerWalletAddr; uint256 maxCapacity; uint64[] nonBusinessDays; address businessDayRegistryAddr; } struct IPoolOverviewStateFlex { address poolAddr; uint256 interestRate; uint256 dailyInterestRate; uint256 totalPrincipalEarningInterest; uint256 totalInterestAccrued; uint256 totalAssetsDeposited; uint256 totalAssetsWithdrawn; uint256 exchangeRate; uint256 totalSupply; uint256 totalRequestedShares; uint256 totalRequestedAssets; uint256 totalAssetsTransitioningIn; uint256 totalSharesTransitioningIn; uint256 totalAssetsDueForWithdraws; uint256 totalFees; uint256 feesOutstanding; uint64[] nonBusinessDays; uint8 state; uint256 lastDayAccrued; } struct IPoolAccountStateFlex { address poolAddr; address accountAddr; uint256 tokenBalance; uint256 maxWithdrawRequest; uint256 maxRedeemRequest; uint256 requestedSharesOf; uint256 requestedAssetsOf; uint256 principalEarningInterest; uint256 interestAccrued; uint256 assetsDeposited; uint256 assetsWithdrawn; uint256 sharesTransitioningIn; uint256 assetsTransitioningIn; uint256 assetsDueForWithdraws; uint256 sharesDueForWithdraws; } struct PoolAddressListFlex { address liquidityAsset; address poolAdmin; address serviceConfiguration; address withdrawDepositControllerFactoryFlex; address poolControllerFactoryFlex; address vaultFactory; address poolAccessControlFactory; address businessDayRegistryFactory; } /** * @title The interface for liquidity pools. */ interface IPoolFlex is IPoolBase { /** * @dev Emitted when tokens are deposited into the vault via the mint and deposit methods. */ event Deposit( address indexed sender, address indexed owner, uint256 assets, uint256 shares ); /** * @dev Emitted when shares are withdrawn from the vault by a depositor in the redeem or withdraw methods. */ event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /**W * @dev The PoolController contract */ function poolController() external view returns (IPoolControllerFlex); /** * @dev The WithdrawController contract */ function withdrawDepositController() external view returns (IWithdrawDepositControllerFlex); /** * @dev The current configurable pool settings. */ function settings() external view returns (IPoolConfigurableSettingsFlex calldata settings); /** * @dev The current pool state. */ function state() external view returns (IPoolLifeCycleStateFlex); function borrowerVaultAddr() external view returns (address); /** * @dev The pool accounting variables; */ function accountings() external view returns (IPoolAccountingsFlex memory); function closeOfWithdrawTime() external view returns (uint256); function closeOfDepositTime() external view returns (uint256); function transferInDays() external view returns (uint256); function transferOutDays() external view returns (uint256); function businessDayRegistry() external view returns (IBusinessDayRegistry); /** * @dev Callback from the pool controller when the pool is activated */ function onActivated() external; function setDailyInterestRate( uint256 _interestRate, uint256 _estimatedDailyRate ) external; function dailyInterestAccural() external; function applyDailyRate(uint256 principal) external returns (uint256); function annualAPRToDailyRate( uint256 annualAPR, uint256 _estimatedDailyRate ) external view returns (uint256 _dailyInterestRate); function interestRate() external view returns (uint256 assets); function exchangeRate() external view returns (uint256 _exchangeRate); function getPoolConfiguration() external view returns (IPoolConfigurationStateFlex memory); function getPoolOverview() external view returns (IPoolOverviewStateFlex memory); function getPoolAccountState( address accountAddr ) external view returns (IPoolAccountStateFlex memory); /** * @dev Calculate the total amount of underlying assets held by the vault, * excluding any assets due for withdrawal. */ function totalAvailableAssets() external view returns (uint256); /** * @dev The total available supply that is not marked for withdrawal */ function totalAvailableSupply() external view returns (uint256); function convertToShares( uint256 assets ) external view returns (uint256 shares); function convertToAssets( uint256 shares ) external view returns (uint256 assets); function deposit( uint256 assets, address lender ) external returns (uint256 shares, uint256 transferInDayTimestamp); function totalAssetsDueForWithdraws() external view returns (uint256); function feesPaidDown(uint256 paidAmount) external; function withdrawEvents() external view returns (IPoolLenderWithdrawEvent[] memory); function releaseWithdrawal( uint256 eventId ) external returns (IPoolLenderWithdrawEvent memory ev); function repayLoans(uint256 assets, uint256 eventId) external; function nonBusinessDays() external view returns (uint64[] memory); function updateNonBusinessDays(uint64[] memory _timestamps) external; function topOffSharesDueToExchangeRateDecrease( address lender, uint256 catchupShares ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title The interface for interacting with Terms of Service Acceptance Registry. */ interface IPoolRegistry { function version() external pure returns (uint16); function addPool(address pool) external; function pools() external returns (address[] memory); function updatePoolData(address poolAddr) external; function isPoolRegistered(address poolAddr) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title Interface that exposes methods to request withdraws / redeems. * @dev Terminology and design informed to complement ERC4626. */ interface IRequestWithdrawable { /** * @dev Returns the maximum number of `shares` that can be * requested to be redeemed from the owner balance with a single * `requestRedeem` call in the current block. * * Note: This is equivalent of EIP-4626 `maxRedeem` */ function maxRedeemRequest( address owner ) external view returns (uint256 maxShares); /** * @dev Returns the maximum amount of underlying `assets` that can be * requested to be withdrawn from the owner balance with a single * `requestWithdraw` call in the current block. * * Note: This is equivalent of EIP-4626 `maxWithdraw` */ function maxWithdrawRequest( address owner ) external view returns (uint256 maxAssets); /** * @dev Simulate the effects of a redeem request at the current block. * Returns the amount of underlying assets that would be requested if this * entire redeem request were to be processed at the current block. * * Note: This is equivalent of EIP-4626 `previewRedeem` */ function previewRedeemRequest( uint256 shares ) external view returns (uint256 assets); /** * @dev Simulate the effects of a withdrawal request at the current block. * Returns the amount of `shares` that would be burned if this entire * withdrawal request were to be processed at the current block. * * Note: This is equivalent of EIP-4626 `previewWithdraw` */ function previewWithdrawRequest( uint256 assets ) external view returns (uint256 shares); /** * @dev Submits a withdrawal request, incurring a fee. */ function requestRedeem(uint256 shares) external returns (uint256 assets); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; struct SerivceAddressList { address[] liquidityAssets; address tosAcceptanceRegistry; address loanFactory; address poolFactoryAddress; address queryLibAddress; address poolLibAddress; address loanLibAddress; address poolControllerFactoryAddress; address withdrawControllerFactoryAddress; address vaultFactoryAddress; address poolAccessControlFactoryAddress; } /** * @title The protocol global Service Configuration */ interface IServiceConfiguration { /** * @dev Emitted when an address is changed. */ event AddressSet(bytes32 which, address addr); /** * @dev Emitted when a liquidity asset is set. */ event LiquidityAssetSet(address addr, bool value); /** * @dev Emitted when a parameter is set. */ event ParameterSet(bytes32, uint256 value); /** * @dev Emitted when the protocol is paused. */ event ProtocolPaused(bool paused); /** * @dev Emitted when a loan factory is set */ event LoanFactorySet(address indexed factory); event PoolFactorySet(address indexed factory); event QueryLibSet(address indexed factory); event LoanLibSet(address indexed factory); event PoolLibSet(address indexed factory); event PoolAdminWalletSet(address indexed factory); /** * @dev Emitted when the TermsOfServiceRegistry is set */ event TermsOfServiceRegistrySet(address indexed registry); /** * @dev checks if a given address has the Operator role */ function isOperator(address addr) external view returns (bool); /** * @dev checks if a given address has the Deployer role */ function isDeployer(address addr) external view returns (bool); /** * @dev checks if a given address has the Deployer role */ function isPoolAdmin(address addr) external view returns (bool); /** * @dev checks if a given address has the Deployer role */ function isBorrower(address addr) external view returns (bool); /** * @dev Whether the protocol is paused. */ function paused() external view returns (bool); /** * @dev Whether an address is supported as a liquidity asset. */ function isLiquidityAsset(address addr) external view returns (bool); /** * @dev Address of the Terms of Service acceptance registry. */ function tosAcceptanceRegistry() external view returns (address); /** * @dev Sets whether a loan factory is valid * @param addr Address of loan factory */ function setLoanFactory(address addr) external; function setPoolFactory(address addr) external; function setQueryLib(address addr) external; function setPoolLib(address addr) external; function setLoanLib(address addr) external; function getLoanFactory() external view returns (address); function getPoolFactory() external view returns (address); function getQueryLib() external view returns (address); function getLoanLib() external view returns (address); function getPoolLib() external view returns (address); function setPoolAdminWallet(address addr) external; function getPoolAdminWallet() external view returns (address); /** * @dev Sets the ToSAcceptanceRegistry for the protocol * @param addr Address of registry */ function setToSAcceptanceRegistry(address addr) external; /** * @dev Sets supported liquidity assets for the protocol. Callable by the operator. * @param addr Address of liquidity asset * @param value Whether supported or not */ function setLiquidityAsset(address addr, bool value) external; function getServiceAddressList() external view returns (SerivceAddressList memory setLoanFactoryerivceAddressList); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "./IServiceConfiguration.sol"; struct SerivceAddressListV3 { address[] liquidityAssets; address tosAcceptanceRegistry; address loanFactory; address poolFactoryAddress; address poolFactoryFlexAddress; address queryLibAddress; address poolLibAddress; address poolLibFlexAddress; address loanLibAddress; address poolControllerFactoryAddress; address withdrawControllerFactoryAddress; address vaultFactoryAddress; address poolAccessControlFactoryAddress; address poolControllerFactoryFlexAddress; address withdrawDepositControllerFactoryFlexAddress; address poolRegistryAddress; } enum IFactoryType { PoolFactory, LoanFactory, VaultFactory, PoolFactoryFlex, PoolControllerFactory, PoolLibFlex, PoolControllerFactoryFlex, WithdrawDepositControllerFactoryFlex, WithdrawControllerFactory, PoolAccessControlFactory } struct LegacyFactoryStruct { IFactoryType factoryType; address factoryAddress; } /** * @title The protocol global Service Configuration */ interface IServiceConfigurationV3 is IServiceConfiguration { event PoolFactoryFlexSet(address indexed factory); event PoolLibFlexSet(address indexed factory); event PoolRegistrySet(address indexed factory); function version() external pure returns (uint16); function isAutomation(address addr) external view returns (bool); function setPoolFactoryFlex(address addr) external; function setPoolLibFlex(address addr) external; function setPoolRegistry(address addr) external; function getPoolRegistry() external view returns (address); function getPoolFactoryFlex() external view returns (address); function getPoolLibFlex() external view returns (address); function getLegacyFactories() external view returns (LegacyFactoryStruct[] memory legacyFactories); function getServiceAddressListV3() external view returns (SerivceAddressListV3 memory addressList); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /** * @title Interface for the Vault. * @dev Vaults simply hold a balance, and allow withdrawals by the Vault's owner. */ interface IVault { /** * @dev Emitted on ERC20 withdrawals */ event WithdrewERC20( address indexed asset, uint256 amount, address indexed receiver ); /** * @dev Emitted on ERC721 withdrawals */ event WithdrewERC721( address indexed asset, uint256 tokenId, address receiver ); /** * @dev Withdraws ERC20 of a given asset */ function withdrawERC20( address asset, uint256 amount, address receiver ) external; /** * @dev Withdraws ERC20 of a given asset */ function withdrawERC20ToBorrowerWallet( address asset, uint256 amount ) external; function payFees(address asset, uint256 amount) external; function repayLoan(address asset, uint256 amount) external; /** * @dev Withdraws ERC721 with specified tokenId */ function withdrawERC721( address asset, uint256 tokenId, address receiver ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {SafeMath} from "@openzeppelin/contracts/utils/math/SafeMath.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {IERC20MetadataUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; import "../interfaces/IPoolFlex.sol"; import "../interfaces/IServiceConfigurationV3.sol"; import "../interfaces/IVault.sol"; /** * @title Collection of functions used by the Pool and PoolController. */ library PoolLibFlex { using SafeERC20 for IERC20; using SafeMath for uint256; using EnumerableSet for EnumerableSet.AddressSet; error InterestRateTooHigh(uint256); uint256 public constant RAY = 10 ** 27; function version() public pure returns (uint16) { return 256 * 1 + 0; } function getPoolFlexConfigurationState( address pool ) public view returns (IPoolConfigurationStateFlex memory _poolConfigurationState) { IPoolFlex poolFlex = IPoolFlex(pool); IPoolControllerFlex poolController = IPoolControllerFlex( address(poolFlex.poolController()) ); return IPoolConfigurationStateFlex({ poolAddr: pool, dailyOriginationFeeRate: poolController .dailyOriginationFeeRate(), originationFee: poolController.originationFee(), closeOfDepositTime: poolController.closeOfDepositTime(), closeOfWithdrawTime: poolController.closeOfWithdrawTime(), transferInDays: poolController.transferInDays(), transferOutDays: poolController.transferOutDays(), liquidityAssetAddr: poolFlex.liquidityAssetAddr(), poolAdminAddr: poolFlex.admin(), poolControllerAddr: address(poolFlex.poolController()), withdrawControllerAddr: address( poolFlex.withdrawDepositController() ), borrowerVaultAddr: poolFlex.borrowerVaultAddr(), name: ERC20Upgradeable(pool).name(), symbol: ERC20Upgradeable(pool).symbol(), borrowerManagerAddr: poolFlex.borrowerManagerAddr(), borrowerWalletAddr: poolFlex.borrowerWalletAddr(), maxCapacity: poolController.settings().maxCapacity, nonBusinessDays: poolFlex.nonBusinessDays(), businessDayRegistryAddr: address(poolFlex.businessDayRegistry()) }); } function getPoolFlexOverviewState( address poolAddr ) public view returns (IPoolOverviewStateFlex memory _poolOverviewState) { IPoolFlex poolFlex = IPoolFlex(poolAddr); IWithdrawDepositControllerFlex withdrawDepositController = IWithdrawDepositControllerFlex( address(poolFlex.withdrawDepositController()) ); IPoolAccountingsFlex memory accountings = poolFlex.accountings(); return IPoolOverviewStateFlex({ poolAddr: poolAddr, interestRate: accountings.interestRate, dailyInterestRate: accountings.dailyInterestRate, totalPrincipalEarningInterest: accountings .totalPrincipalEarningInterest, totalInterestAccrued: accountings.totalInterestAccrued, totalAssetsDeposited: accountings.totalAssetsDeposited, totalAssetsWithdrawn: accountings.totalAssetsWithdrawn, exchangeRate: accountings.exchangeRate, totalSupply: poolFlex.totalSupply(), totalRequestedShares: withdrawDepositController .totalRequestedShares(), totalRequestedAssets: withdrawDepositController .totalRequestedAssets(), totalAssetsTransitioningIn: withdrawDepositController .totalAssetsTransitioningIn(), totalSharesTransitioningIn: withdrawDepositController .totalSharesTransitioningIn(), totalAssetsDueForWithdraws: withdrawDepositController .totalAssetsDueForWithdraws(), totalFees: accountings.totalFees, feesOutstanding: accountings.feesOutstanding, nonBusinessDays: poolFlex.nonBusinessDays(), state: uint8(poolFlex.state()), lastDayAccrued: accountings.lastDayAccrued }); } function roundDiv(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + (b / 2); return c / b; } function roundUpDiv(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + (b -1); return c / b; } function getPoolAccountState( address poolAddr, address accountAddr ) public view returns (IPoolAccountStateFlex memory _poolAccountState) { IPoolFlex pool = IPoolFlex(poolAddr); address withdrawDepositController = address( pool.withdrawDepositController() ); IWithdrawDepositControllerFlex withdrawDepositControllerFlex = IWithdrawDepositControllerFlex( withdrawDepositController ); IPoolLenderTotals memory lenderTotals = withdrawDepositControllerFlex .lenderTotals(accountAddr); uint256 tokenBalance = pool.balanceOf(accountAddr); uint256 principalExpanded = ((tokenBalance - lenderTotals.sharesTransitioningIn - lenderTotals.requestedShares) * IPoolFlex(pool).accountings().exchangeRate); uint256 principalEarningInterest = roundUpDiv(principalExpanded, 1e18); uint256 interestAccrued; if ( (principalEarningInterest + lenderTotals.assetsTransitioningIn + lenderTotals.requestedAssets + lenderTotals.assetsWithdrawn ) >lenderTotals.assetsDeposited) { interestAccrued = principalEarningInterest + lenderTotals.assetsTransitioningIn + lenderTotals.requestedAssets + lenderTotals.assetsWithdrawn - lenderTotals.assetsDeposited; } else { interestAccrued = 0; } uint256 maxWithdrawRequest = pool.maxWithdrawRequest(accountAddr); uint256 maxRedeemRequest = pool.maxRedeemRequest(accountAddr); return IPoolAccountStateFlex({ poolAddr: address(pool), accountAddr: accountAddr, tokenBalance: tokenBalance, maxWithdrawRequest: maxWithdrawRequest, maxRedeemRequest: maxRedeemRequest, requestedSharesOf: lenderTotals.requestedShares, requestedAssetsOf: lenderTotals.requestedAssets, principalEarningInterest: principalEarningInterest, interestAccrued: interestAccrued, assetsDeposited: lenderTotals.assetsDeposited, assetsWithdrawn: lenderTotals.assetsWithdrawn, sharesTransitioningIn: lenderTotals.sharesTransitioningIn, assetsTransitioningIn: lenderTotals.assetsTransitioningIn, assetsDueForWithdraws: lenderTotals.assetsDueForWithdraws, sharesDueForWithdraws: lenderTotals.sharesDueForWithdraws }); } function originalAnnualAPRToDailyRate( uint256 _interestRate ) public pure returns (uint256) { if (_interestRate > 2000) revert InterestRateTooHigh(_interestRate); uint256 start = 1e18 + ((_interestRate * 1e18) / 1e4); uint256 ratio = 1e18 + ((_interestRate * 1e18) / 1e4 / 365); uint256 min = 1e18 + ((_interestRate * 1e18) / 1e4 / 400); uint256 max = ratio; while (max - min > 1e10) { uint256 mid = (min + max) / 2; uint256 midPow = pow365(mid); if (midPow == start) { return mid; } else if (midPow < start) { min = mid; } else { max = mid; } } return min - 1e18; } function annualAPRToDailyRate( uint256 _interestRate, uint256 _estimatedDailyRate ) public pure returns (uint256) { // uint256 originalRet = originalAnnualAPRToDailyRate(_interestRate); if (_interestRate > 2000) revert InterestRateTooHigh(_interestRate); uint256 start = 1e18 + ((_interestRate * 1e18) / 1e4); uint256 ratio = 1e18 + ((_interestRate * 1e18) / 1e4 / 365); uint256 min; if (ratio < (1e18 + _estimatedDailyRate)) { min = 1e18 + ((_interestRate * 1e18) / 1e4 / 420); } else { uint256 diff = ratio - (1e18 + _estimatedDailyRate); min = ratio - 2 * (diff); if (pow365(min) > start) { min = 1e18 + ((_interestRate * 1e18) / 1e4 / 420); } } uint256 max = ratio; while (max - min > 1e10) { uint256 mid = (min + max) / 2; uint256 midPow = pow365(mid); if (midPow > start && midPow - start < 1e10) { return mid - 1e18; } else if (midPow < start && start - midPow < 1e10) { return mid - 1e18; } else if (midPow == start) { return mid - 1e18; } else if (midPow < start) { min = mid; } else { max = mid; } } return min - 1e18; } // Helper function to calculate power (base^exp) function pow365(uint256 base) internal pure returns (uint256) { uint256 result = (base * base) / 1e18; // 2 result = (result * result) / 1e18; // 4 uint256 result4 = result; result = (result * result) / 1e18; // 8 uint256 result8 = result; result = (result * result) / 1e18; // 16 result = (result * result) / 1e18; // 32 uint256 result32 = result; result = (result * result) / 1e18; // 64 uint256 result64 = result; result = (result * result) / 1e18; // 128 result = (result * result) / 1e18; // 256 result = (result * result64) / 1e18; // 320 result = (result * result32) / 1e18; // 352 result = (result * result8) / 1e18; // 360 result = (result * result4) / 1e18; // 364 result = (result * base) / 1e18; // 365 return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @title BeaconImplementation base contract * @dev Base contract that overrides the constructor to disable initialization. */ abstract contract BeaconImplementation is Initializable { /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } }
{ "optimizer": { "enabled": true, "runs": 10 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": { "contracts/libraries/PoolLibFlex.sol": { "PoolLibFlex": "0x78bfc8a7197abfb81d4774e7936a76092be2e169" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"AccuralCalledTooEarly","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"ExceedsMaxDeposit","type":"error"},{"inputs":[],"name":"ExcessFeePayment","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"ExcessWithdraw","type":"error"},{"inputs":[],"name":"InvalidAccess","type":"error"},{"inputs":[],"name":"InvalidLoan","type":"error"},{"inputs":[],"name":"InvalidPoolSetting","type":"error"},{"inputs":[],"name":"InvalidRepayment","type":"error"},{"inputs":[],"name":"NotBorrowerManager","type":"error"},{"inputs":[],"name":"NotLender","type":"error"},{"inputs":[],"name":"NotPoolAdmin","type":"error"},{"inputs":[],"name":"NotPoolController","type":"error"},{"inputs":[],"name":"NotWithdrawController","type":"error"},{"inputs":[],"name":"PoolInvalidState","type":"error"},{"inputs":[],"name":"PoolNotActive","type":"error"},{"inputs":[],"name":"PoolPaused","type":"error"},{"inputs":[],"name":"TransferDisabled","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"ZeroDeposit","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[],"name":"PoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"transferInDayTimestamp","type":"uint256"}],"name":"PoolDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"RedeemReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"RedeemRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":true,"internalType":"uint256","name":"eventId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"RepayLoanToLender","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lender","type":"address"},{"indexed":true,"internalType":"uint256","name":"eventId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"RepayToPoolProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"accountings","outputs":[{"components":[{"internalType":"uint256","name":"interestRate","type":"uint256"},{"internalType":"uint256","name":"dailyInterestRate","type":"uint256"},{"internalType":"uint256","name":"totalPrincipalEarningInterest","type":"uint256"},{"internalType":"uint256","name":"totalInterestAccrued","type":"uint256"},{"internalType":"uint256","name":"totalAssetsDeposited","type":"uint256"},{"internalType":"uint256","name":"totalAssetsWithdrawn","type":"uint256"},{"internalType":"uint256","name":"exchangeRate","type":"uint256"},{"internalType":"uint256","name":"lastDayAccrued","type":"uint256"},{"internalType":"uint256","name":"totalFees","type":"uint256"},{"internalType":"uint256","name":"feesOutstanding","type":"uint256"},{"internalType":"uint256","name":"interstRateSetTime","type":"uint256"}],"internalType":"struct IPoolAccountingsFlex","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activatedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"annualAPR","type":"uint256"},{"internalType":"uint256","name":"estimatedDailyRate","type":"uint256"}],"name":"annualAPRToDailyRate","outputs":[{"internalType":"uint256","name":"_dailyInterestRate","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"principal","type":"uint256"}],"name":"applyDailyRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowerManagerAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowerVaultAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowerWalletAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"businessDayRegistry","outputs":[{"internalType":"contract IBusinessDayRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeOfDepositTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeOfWithdrawTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dailyInterestAccural","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"lender","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"transferInDayTimestamp","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"_exchangeRate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"paidAmount","type":"uint256"}],"name":"feesPaidDown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"accountAddr","type":"address"}],"name":"getPoolAccountState","outputs":[{"components":[{"internalType":"address","name":"poolAddr","type":"address"},{"internalType":"address","name":"accountAddr","type":"address"},{"internalType":"uint256","name":"tokenBalance","type":"uint256"},{"internalType":"uint256","name":"maxWithdrawRequest","type":"uint256"},{"internalType":"uint256","name":"maxRedeemRequest","type":"uint256"},{"internalType":"uint256","name":"requestedSharesOf","type":"uint256"},{"internalType":"uint256","name":"requestedAssetsOf","type":"uint256"},{"internalType":"uint256","name":"principalEarningInterest","type":"uint256"},{"internalType":"uint256","name":"interestAccrued","type":"uint256"},{"internalType":"uint256","name":"assetsDeposited","type":"uint256"},{"internalType":"uint256","name":"assetsWithdrawn","type":"uint256"},{"internalType":"uint256","name":"sharesTransitioningIn","type":"uint256"},{"internalType":"uint256","name":"assetsTransitioningIn","type":"uint256"},{"internalType":"uint256","name":"assetsDueForWithdraws","type":"uint256"},{"internalType":"uint256","name":"sharesDueForWithdraws","type":"uint256"}],"internalType":"struct IPoolAccountStateFlex","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolConfiguration","outputs":[{"components":[{"internalType":"address","name":"poolAddr","type":"address"},{"internalType":"uint256","name":"dailyOriginationFeeRate","type":"uint256"},{"internalType":"uint256","name":"originationFee","type":"uint256"},{"internalType":"uint256","name":"closeOfDepositTime","type":"uint256"},{"internalType":"uint256","name":"closeOfWithdrawTime","type":"uint256"},{"internalType":"uint256","name":"transferInDays","type":"uint256"},{"internalType":"uint256","name":"transferOutDays","type":"uint256"},{"internalType":"address","name":"liquidityAssetAddr","type":"address"},{"internalType":"address","name":"poolAdminAddr","type":"address"},{"internalType":"address","name":"poolControllerAddr","type":"address"},{"internalType":"address","name":"withdrawControllerAddr","type":"address"},{"internalType":"address","name":"borrowerVaultAddr","type":"address"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"borrowerManagerAddr","type":"address"},{"internalType":"address","name":"borrowerWalletAddr","type":"address"},{"internalType":"uint256","name":"maxCapacity","type":"uint256"},{"internalType":"uint64[]","name":"nonBusinessDays","type":"uint64[]"},{"internalType":"address","name":"businessDayRegistryAddr","type":"address"}],"internalType":"struct IPoolConfigurationStateFlex","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolOverview","outputs":[{"components":[{"internalType":"address","name":"poolAddr","type":"address"},{"internalType":"uint256","name":"interestRate","type":"uint256"},{"internalType":"uint256","name":"dailyInterestRate","type":"uint256"},{"internalType":"uint256","name":"totalPrincipalEarningInterest","type":"uint256"},{"internalType":"uint256","name":"totalInterestAccrued","type":"uint256"},{"internalType":"uint256","name":"totalAssetsDeposited","type":"uint256"},{"internalType":"uint256","name":"totalAssetsWithdrawn","type":"uint256"},{"internalType":"uint256","name":"exchangeRate","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"totalRequestedShares","type":"uint256"},{"internalType":"uint256","name":"totalRequestedAssets","type":"uint256"},{"internalType":"uint256","name":"totalAssetsTransitioningIn","type":"uint256"},{"internalType":"uint256","name":"totalSharesTransitioningIn","type":"uint256"},{"internalType":"uint256","name":"totalAssetsDueForWithdraws","type":"uint256"},{"internalType":"uint256","name":"totalFees","type":"uint256"},{"internalType":"uint256","name":"feesOutstanding","type":"uint256"},{"internalType":"uint64[]","name":"nonBusinessDays","type":"uint64[]"},{"internalType":"uint8","name":"state","type":"uint8"},{"internalType":"uint256","name":"lastDayAccrued","type":"uint256"}],"internalType":"struct IPoolOverviewStateFlex","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"liquidityAsset","type":"address"},{"internalType":"address","name":"poolAdmin","type":"address"},{"internalType":"address","name":"serviceConfiguration","type":"address"},{"internalType":"address","name":"withdrawDepositControllerFactoryFlex","type":"address"},{"internalType":"address","name":"poolControllerFactoryFlex","type":"address"},{"internalType":"address","name":"vaultFactory","type":"address"},{"internalType":"address","name":"poolAccessControlFactory","type":"address"},{"internalType":"address","name":"businessDayRegistryFactory","type":"address"}],"internalType":"struct PoolAddressListFlex","name":"poolAddressListFlex","type":"tuple"},{"components":[{"internalType":"uint256","name":"maxCapacity","type":"uint256"},{"internalType":"address","name":"borrowerManagerAddr","type":"address"},{"internalType":"address","name":"borrowerWalletAddr","type":"address"},{"internalType":"uint256","name":"closeOfDepositTime","type":"uint256"},{"internalType":"uint256","name":"closeOfWithdrawTime","type":"uint256"},{"internalType":"uint256","name":"originationFee","type":"uint256"},{"internalType":"uint256","name":"dailyOriginationFeeRate","type":"uint256"},{"internalType":"uint256","name":"transferInDays","type":"uint256"},{"internalType":"uint256","name":"transferOutDays","type":"uint256"}],"internalType":"struct IPoolConfigurableSettingsFlex","name":"poolSettings","type":"tuple"},{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"interestRate","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"isPermittedLender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityAssetAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityPoolAssets","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeemRequest","outputs":[{"internalType":"uint256","name":"maxShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdrawRequest","outputs":[{"internalType":"uint256","name":"maxAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonBusinessDays","outputs":[{"internalType":"uint64[]","name":"","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onActivated","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolAccessControl","outputs":[{"internalType":"contract IPoolAccessControl","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolController","outputs":[{"internalType":"contract IPoolControllerFlex","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolType","outputs":[{"internalType":"enum IPoolType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeemRequest","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdrawRequest","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"eventId","type":"uint256"}],"name":"releaseWithdrawal","outputs":[{"components":[{"internalType":"uint256","name":"requestedShares","type":"uint256"},{"internalType":"uint256","name":"requestedAssets","type":"uint256"},{"internalType":"uint256","name":"transferOutDayTimestamp","type":"uint256"},{"internalType":"uint256","name":"requestTimestamp","type":"uint256"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"uint256","name":"eventId","type":"uint256"}],"internalType":"struct IPoolLenderWithdrawEvent","name":"ev","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"uint256","name":"eventId","type":"uint256"}],"name":"repayLoans","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"requestRedeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"serviceConfiguration","outputs":[{"internalType":"contract IServiceConfigurationV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_interestRate","type":"uint256"},{"internalType":"uint256","name":"_estimatedDailyRate","type":"uint256"}],"name":"setDailyInterestRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settings","outputs":[{"components":[{"internalType":"uint256","name":"maxCapacity","type":"uint256"},{"internalType":"address","name":"borrowerManagerAddr","type":"address"},{"internalType":"address","name":"borrowerWalletAddr","type":"address"},{"internalType":"uint256","name":"closeOfDepositTime","type":"uint256"},{"internalType":"uint256","name":"closeOfWithdrawTime","type":"uint256"},{"internalType":"uint256","name":"originationFee","type":"uint256"},{"internalType":"uint256","name":"dailyOriginationFeeRate","type":"uint256"},{"internalType":"uint256","name":"transferInDays","type":"uint256"},{"internalType":"uint256","name":"transferOutDays","type":"uint256"}],"internalType":"struct IPoolConfigurableSettingsFlex","name":"poolSettings","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"enum IPoolLifeCycleStateFlex","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"lender","type":"address"},{"internalType":"uint256","name":"catchupShares","type":"uint256"}],"name":"topOffSharesDueToExchangeRateDecrease","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssetsDueForWithdraws","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAvailableAssets","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAvailableSupply","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferInDays","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferOutDays","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"_timestamps","type":"uint64[]"}],"name":"updateNonBusinessDays","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"withdrawDepositController","outputs":[{"internalType":"contract IWithdrawDepositControllerFlex","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawEvents","outputs":[{"components":[{"internalType":"uint256","name":"requestedShares","type":"uint256"},{"internalType":"uint256","name":"requestedAssets","type":"uint256"},{"internalType":"uint256","name":"transferOutDayTimestamp","type":"uint256"},{"internalType":"uint256","name":"requestTimestamp","type":"uint256"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"uint256","name":"eventId","type":"uint256"}],"internalType":"struct IPoolLenderWithdrawEvent[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405261029a6066553480156200001757600080fd5b506200002262000028565b620000e9565b600054610100900460ff1615620000955760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e7576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61592180620000f96000396000f3fe608060405234801561001057600080fd5b50600436106102f05760003560e01c806370a082311161018f57806370a0823114610515578063712577e21461052857806377c020a91461053057806378880710146105435780637c3a00fd1461055857806380bb521d146105605780638311fb62146105685780638456ec6e1461058857806394879a1c1461059957806395d89b41146105a1578063a0786081146105a9578063a3f8547714610636578063a457c2d714610649578063a9059cbb1461065c578063aa2f892d1461066f578063aa696ef814610682578063b1dd61b614610695578063b80945e9146106a8578063c19d93fb146106bd578063c2f39e7a146106d2578063c6e6f592146106e5578063ca01302d146106f8578063db6b207414610700578063dd62ed3e14610713578063de0c7fdf14610726578063def53cf314610746578063e06174e414610759578063e38ab46c1461076e578063e40b858514610783578063e5fc6d6d146102f5578063e8af8fa31461078b578063f851a4401461079e57600080fd5b806301e1d114146102f557806303210d3e1461031057806304bce9e61461032557806306fdde031461033a57806307a2d13a1461034f57806307cdb58a14610362578063095ea7b31461036c5780630b24697f1461038f5780631311b7bf146103a257806313b98c0f146102f557806316bc64f4146103b857806318160ddd146103cb5780631e0f9fd6146103d35780631f7bdb59146103e6578063214ebb52146103ee57806323b872dd14610401578063313ce56714610414578063384b54e91461042357806339509351146104365780633ba0b9a914610449578063402d267d1461045157806348a67aa9146104645780634aa9d585146104775780635214d8ca1461048a57806354fd4d5014610492578063597be6d1146104a257806359d5cd7b146104ab5780635d5366de146104be5780636d36daf0146104c65780636e3480b7146104d95780636e553f65146104e15780637058162314610502575b600080fd5b6102fd6107a6565b6040519081526020015b60405180910390f35b610318610826565b60405161030791906143ab565b61032d610894565b6040516103079190614403565b6103426109b1565b6040516103079190614571565b6102fd61035d366004614584565b610a43565b61036a610a70565b005b61037f61037a3660046145bd565b610f70565b6040519015158152602001610307565b61036a61039d3660046145bd565b610f88565b60675461010090046001600160a01b0316610318565b61036a6103c63660046146f9565b610fc1565b6035546102fd565b61036a6103e136600461488b565b611141565b6102fd61197e565b6102fd6103fc3660046149ab565b6119ec565b61037f61040f3660046149cd565b611a70565b60405160068152602001610307565b61036a610431366004614584565b611a94565b61037f6104443660046145bd565b611bec565b606f546102fd565b6102fd61045f366004614a0e565b611c0e565b61036a6104723660046149ab565b611d41565b607554610318906001600160a01b031681565b610318612017565b6040516101008152602001610307565b6102fd60775481565b6102fd6104b9366004614584565b612061565b6102fd61206c565b606554610318906001600160a01b031681565b6102fd6120b6565b6104f46104ef366004614a2b565b612100565b604051610307929190614a5b565b607454610318906001600160a01b031681565b6102fd610523366004614a0e565b612642565b6102fd61265d565b607654610318906001600160a01b031681565b61054b6126a7565b6040516103079190614aa9565b6069546102fd565b6102fd612719565b61057b610576366004614a0e565b612815565b6040516103079190614af7565b6068546001600160a01b0316610318565b61036a61291e565b610342612957565b6105b1612966565b6040516103079190600061016082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151818401525061014080840151818401525092915050565b61037f610644366004614a0e565b612a2c565b61037f6106573660046145bd565b612a9e565b61037f61066a3660046145bd565b612b19565b6102fd61067d366004614584565b612b27565b6102fd610690366004614584565b612e21565b60675460ff166040516103079190614bca565b6106b0612e4f565b6040516103079190614be4565b6106c5612f5f565b6040516103079190614d51565b61036a6106e03660046149ab565b612fcd565b6102fd6106f3366004614584565b61317a565b610318613197565b6102fd61070e366004614a0e565b6131e1565b6102fd610721366004614d65565b613253565b610739610734366004614584565b61327e565b6040516103079190614d93565b6102fd610754366004614584565b61349a565b6107616134a5565b6040516103079190614e09565b61077661357e565b6040516103079190614e18565b6102fd6135f0565b6102fd610799366004614a0e565b61363a565b610318613648565b6074546040805163f216a1a360e01b815290516000926001600160a01b03169163f216a1a39160048083019260209291908290030181865afa1580156107f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108149190614e59565b606b546108219190614e88565b905090565b60755460408051630190869f60e11b815290516000926001600160a01b0316916303210d3e9160048083019260209291908290030181865afa158015610870573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108219190614ea6565b61093560405180610260016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160608152602001600060ff168152602001600081525090565b60405163181021ed60e01b81527378bfc8a7197abfb81d4774e7936a76092be2e1699063181021ed9061096c9030906004016143ab565b600060405180830381865af4158015610989573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108219190810190614f43565b6060603680546109c090615084565b80601f01602080910402602001604051908101604052809291908181526020018280546109ec90615084565b8015610a395780601f10610a0e57610100808354040283529160200191610a39565b820191906000526020600020905b815481529060010190602001808311610a1c57829003601f168201915b5050505050905090565b6000610a6a670de0b6b3a7640000610a64610a5d606f5490565b8590613692565b9061369e565b92915050565b6067546040516250495760e01b81526101009091046001600160a01b0316906250495790610aa29033906004016143ab565b602060405180830381865afa158015610abf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae391906150be565b158015610b625750606754604051637be53ca160e01b81526101009091046001600160a01b031690637be53ca190610b1f9033906004016143ab565b602060405180830381865afa158015610b3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6091906150be565b155b15610b7f5760405162b145b560e31b815260040160405180910390fd5b6000610b8e62015180426150f6565b610b98904261510a565b9050607560009054906101000a90046001600160a01b03166001600160a01b0316635d5366de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c119190614e59565b610c1e62015180426150f6565b1015610c3457610c31620151808261510a565b90505b6070548111610c6457607054604051636692c96d60e11b8152610c5b918391600401614a5b565b60405180910390fd5b6070546000906201518090610c79908461510a565b610c83919061511d565b60705490915060005b82811015610ea757610ca18262015180614e88565b9150610cd4670de0b6b3a7640000610a64606960010154670de0b6b3a7640000610ccb9190614e88565b606f5490613692565b606f55606a54606b54600091670de0b6b3a764000091610cf49190615131565b610cfe919061511d565b90506000670de0b6b3a7640000607560009054906101000a90046001600160a01b03166001600160a01b03166362aada936040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d829190614e59565b606b54610d8f9190615131565b610d99919061511d565b90508160696002016000828254610db09190614e88565b9091555050606c8054839190600090610dca908490614e88565b909155505060718054829190600090610de4908490614e88565b909155505060728054829190600090610dfe908490614e88565b909155505060745460405163fe7eb29160e01b8152600481018690526000916001600160a01b03169063fe7eb291906024016020604051808303816000875af1158015610e4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e739190614e59565b90508060696002016000828254610e8a9190614e88565b925050819055505050508080610e9f90615150565b915050610c8c565b506000610eb762015180426150f6565b610ec1904261510a565b9050607560009054906101000a90046001600160a01b03166001600160a01b0316635d5366de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3a9190614e59565b610f4762015180426150f6565b1015610f5d57610f5a620151808261510a565b90505b6070819055610f6a6136aa565b50505050565b600033610f7e81858561377a565b5060019392505050565b6074546001600160a01b03163314610fb35760405163a59decbf60e01b815260040160405180910390fd5b610fbd828261389e565b5050565b606754604051637be53ca160e01b81526101009091046001600160a01b031690637be53ca190610ff59033906004016143ab565b602060405180830381865afa158015611012573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103691906150be565b15806110b65750607554604080516303e1469160e61b8152905133926001600160a01b03169163f851a4409160048083019260209291908290030181865afa158015611086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110aa9190614ea6565b6001600160a01b031614155b156110d35760405162b145b560e31b815260040160405180910390fd5b6110db6136aa565b6076546040516305af193d60e21b81526001600160a01b03909116906316bc64f49061110b908490600401614e18565b600060405180830381600087803b15801561112557600080fd5b505af1158015611139573d6000803e3d6000fd5b505050505b50565b600054610100900460ff16158080156111615750600054600160ff909116105b80611182575061117030613959565b158015611182575060005460ff166001145b6111e55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c5b565b6000805460ff191660011790558015611208576000805461ff0019166101001790555b6112128383613968565b60408501516067805460016001600160a01b039093166101000260ff19166001600160a81b03199091161791909117905560c0840151670de0b6b3a764000010806112635750620186a08460a00151115b8061127157508351620f4240115b806112865750835169d3c21bcecceda1000000105b8061129c575060208401516001600160a01b0316155b806112b2575060408401516001600160a01b0316155b806112c35750620151808460600151115b806112d45750620151808460800151115b806112e3575060058460e00151115b806112f357506005846101000151115b1561131157604051630fcf47e960e11b815260040160405180910390fd5b60a08401517378bfc8a7197abfb81d4774e7936a76092be2e1699063214ebb529061019061271061134a83670de0b6b3a7640000615131565b611354919061511d565b61135e919061511d565b6040518363ffffffff1660e01b815260040161137b929190614a5b565b602060405180830381865af4158015611398573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bc9190614e59565b60c08501526067546020860151604051637be53ca160e01b81526101009092046001600160a01b031691637be53ca1916113f8916004016143ab565b602060405180830381865afa158015611415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143991906150be565b61145657604051633006171960e21b815260040160405180910390fd5b8451606880546001600160a01b0319166001600160a01b0380841691909117909155608087015160408089015160208a015191516378f4eeeb60e01b815292909316936378f4eeeb936114b29330939192908b90600401615169565b6020604051808303816000875af11580156114d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f59190614ea6565b607580546001600160a01b0319166001600160a01b0392831617905560c08601516040516313db266360e31b8152911690639ed933189061153a9030906004016143ab565b6020604051808303816000875af1158015611559573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157d9190614ea6565b606580546001600160a01b0319166001600160a01b0392831617905560e08601516040516313db266360e31b81526000929190911690639ed93318906115c79030906004016143ab565b6020604051808303816000875af11580156115e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160a9190614ea6565b607680546001600160a01b0319166001600160a01b038381169190911790915560755460408051632ea9b36f60e11b815290519394506000939190921691635d5366de9160048083019260209291908290030181865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116969190614e59565b6116a362015180426150f6565b101561173d576001600160a01b038216633c3cb08b6116c562015180426151a9565b6040516001600160e01b031960e084901b1681526001600160401b039091166004820152602401602060405180830381865afa158015611709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172d91906151d0565b6001600160401b031690506117ba565b604051633c3cb08b60e01b81526001600160401b03421660048201526001600160a01b03831690633c3cb08b90602401602060405180830381865afa15801561178a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ae91906151d0565b6001600160401b031690505b604080516101608101825260008082526020820181905281830181905260608083018290526080830182905260a0808401839052670de0b6b3a764000060c0850181905260e08501879052610100850184905261012085018490526101409094018390526069839055606a839055606b839055606c839055606d839055606e839055606f93909355607085905560718290556072829055607391909155890151908901518883015192516335bb74f560e11b81523060048201526001600160a01b03918216602482015292811660448401521690636b76e9ea906064016020604051808303816000875af11580156118b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118da9190614ea6565b607480546001600160a01b0319166001600160a01b03928316179055606854611907911630600019613999565b6040517f4196df5545177bff7cc5a8e7d409ae30d345a95b556b2eaf6b727038bef3128e90600090a150508015611139576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b60745460408051631f7bdb5960e01b815290516000926001600160a01b031691631f7bdb599160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108219190614e59565b6040516310a75da960e11b81526000907378bfc8a7197abfb81d4774e7936a76092be2e1699063214ebb5290611a289086908690600401614a5b565b602060405180830381865af4158015611a45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a699190614e59565b9392505050565b600033611a7e858285613ae0565b611a89858585613b54565b506001949350505050565b606754604051637be53ca160e01b81526101009091046001600160a01b031690637be53ca190611ac89033906004016143ab565b602060405180830381865afa158015611ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0991906150be565b1580611b895750607554604080516303e1469160e61b8152905133926001600160a01b03169163f851a4409160048083019260209291908290030181865afa158015611b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7d9190614ea6565b6001600160a01b031614155b15611ba65760405162b145b560e31b815260040160405180910390fd5b607254811115611bc9576040516369f9a44760e11b815260040160405180910390fd5b8060696009016000828254611bde919061510a565b9091555061113e90506136aa565b600033610f7e818585611bff8383613253565b611c099190614e88565b61377a565b6000606760019054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8791906150be565b151560011480611c9d5750611c9b82612a2c565b155b80611d2557506075546040805163c19d93fb60e01b815290516001926001600160a01b03169163c19d93fb9160048083019260209291908290030181865afa158015611ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1191906151ed565b6003811115611d2257611d22614bb4565b14155b15611d3257506000919050565b50670de0b6b3a7640000919050565b60675460405163eaf6e48360e01b81526101009091046001600160a01b03169063eaf6e48390611d759033906004016143ab565b602060405180830381865afa158015611d92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db691906150be565b1580611e3657506075546040805163290a6c6560e11b8152905133926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa158015611e06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2a9190614ea6565b6001600160a01b031614155b15611e54576040516369c7961360e01b815260040160405180910390fd5b60745460408051630788807160e41b815290516000926001600160a01b031691637888071091600480830192869291908290030181865afa158015611e9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ec59190810190615290565b9050611ecf61435f565b6000805b8351811015611f335784848281518110611eef57611eef615329565b602002602001015160a0015103611f2157838181518110611f1257611f12615329565b60200260200101519250600191505b80611f2b81615150565b915050611ed3565b50801580611f445750848260200151115b15611f625760405163166877a960e21b815260040160405180910390fd5b607454604051624eb02760e41b8152600481018790526001600160a01b03909116906304eb027090602401600060405180830381600087803b158015611fa757600080fd5b505af1158015611fbb573d6000803e3d6000fd5b505050508382608001516001600160a01b03167f3732b90483b99a3d87ca37d7e421a92c5f07ce3a73a7738320da6ecac265720a84600001518560200151604051612007929190614a5b565b60405180910390a36111396136aa565b6075546040805163290a6c6560e11b815290516000926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa158015610870573d6000803e3d6000fd5b6000610a6a82610a43565b60755460408051632ea9b36f60e11b815290516000926001600160a01b031691635d5366de9160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b60755460408051636e3480b760e01b815290516000926001600160a01b031691636e3480b79160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b600080606760019054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612156573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217a91906150be565b151560010361219c5760405163146f5dc360e21b815260040160405180910390fd5b600180607560009054906101000a90046001600160a01b03166001600160a01b031663c19d93fb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221691906151ed565b600381111561222757612227614bb4565b14612245576040516367e554d160e01b815260040160405180910390fd5b60655460405163babcc53960e01b81526001600160a01b039091169063babcc539906122759033906004016143ab565b602060405180830381865afa158015612292573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b691906150be565b6122d357604051638c38000360e01b815260040160405180910390fd5b6075546040805163290a6c6560e11b8152905133926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa15801561231c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123409190614ea6565b6001600160a01b03160361236757604051638c38000360e01b815260040160405180910390fd5b6075546040805163c19d93fb60e01b815290516003926001600160a01b03169163c19d93fb9160048083019260209291908290030181865afa1580156123b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d591906151ed565b60038111156123e6576123e6614bb4565b14806123fb5750336001600160a01b03851614155b15612419576040516367e554d160e01b815260040160405180910390fd5b61242284611c0e565b8511156124505761243284611c0e565b8585604051632422a34560e11b8152600401610c5b9392919061533f565b8460000361247f5761246184611c0e565b858560405163203e505760e11b8152600401610c5b9392919061533f565b607454606f54606a5460405163ce88b43960e01b81526001600160a01b038881166004830152602482018a905260448201939093526064810191909152600092919091169063ce88b439906084016060604051808303816000875af11580156124ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612510919061535e565b606d805492975090955091925087919060009061252e908490614e88565b909155505060685461254b906001600160a01b0316333089613cf8565b612555858561389e565b61257530612561613197565b6068546001600160a01b0316919089613cf8565b607454604051632b907e9d60e01b8152600481018890526001600160a01b0390911690632b907e9d90602401600060405180830381600087803b1580156125bb57600080fd5b505af11580156125cf573d6000803e3d6000fd5b5050505080606960020160008282546125e89190614e88565b909155505060408051878152602081018690529081018490526001600160a01b038616907f0af19f929dc1d7b34887d6f1a7e36b8d6bc0a9071daf7f65d2bffff866683e739060600160405180910390a250509250929050565b6001600160a01b031660009081526033602052604090205490565b60755460408051633892bbf160e11b815290516000926001600160a01b03169163712577e29160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b60745460408051630788807160e41b815290516060926001600160a01b03169163788807109160048083019260009291908290030181865afa1580156126f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108219190810190615290565b60745460408051637329ef3960e11b815290516000926001600160a01b03169163e653de729160048083019260209291908290030181865afa158015612763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127879190614e59565b607460009054906101000a90046001600160a01b03166001600160a01b031663cd1032086040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127fe9190614e59565b60355461280b919061510a565b610821919061510a565b6128a0604051806101e0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051636695bd3b60e01b81526000907378bfc8a7197abfb81d4774e7936a76092be2e16990636695bd3b906128dc903090879060040161538c565b6101e060405180830381865af41580156128fa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6991906153a6565b6075546001600160a01b031633146129495760405163300863cd60e01b815260040160405180910390fd5b6129516136aa565b42607755565b6060603780546109c090615084565b6129c360405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5060408051610160810182526069548152606a546020820152606b5491810191909152606c546060820152606d546080820152606e5460a0820152606f5460c082015260705460e082015260715461010082015260725461012082015260735461014082015290565b60655460405163babcc53960e01b81526000916001600160a01b03169063babcc53990612a5d9085906004016143ab565b602060405180830381865afa158015612a7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6a91906150be565b60003381612aac8286613253565b905083811015612b0c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610c5b565b611a89828686840361377a565b600033610f7e818585613b54565b6000606760019054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba091906150be565b1515600103612bc25760405163146f5dc360e21b815260040160405180910390fd5b607754600003612be5576040516338c0a90160e11b815260040160405180910390fd5b60655460405163babcc53960e01b81526001600160a01b039091169063babcc53990612c159033906004016143ab565b602060405180830381865afa158015612c32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5691906150be565b612c7357604051638c38000360e01b815260040160405180910390fd5b6075546040805163290a6c6560e11b8152905133926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa158015612cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce09190614ea6565b6001600160a01b031603612d0757604051638c38000360e01b815260040160405180910390fd5b6000612d1233612642565b11612d3057604051638c38000360e01b815260040160405180910390fd5b612d3982610a43565b606b54909150811115612d4b5750606b545b60745460405163014cf1e960e11b815233600482015260248101849052604481018390526001600160a01b0390911690630299e3d290606401600060405180830381600087803b158015612d9e57600080fd5b505af1158015612db2573d6000803e3d6000fd5b505050508060696002016000828254612dcb919061510a565b90915550612dd990506136aa565b336001600160a01b03167f58fe322fc5911ed072ec92f570e517b9793e350eb1ff7be0019fd9f3fade87bc8284604051612e14929190614a5b565b60405180910390a2919050565b606a54600090670de0b6b3a764000090612e3b9082614e88565b612e459084615131565b610a6a919061511d565b604080516102608101825260008082526020820181905281830181905260608083018290526080830182905260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018190526101a083018190526101c083018290526101e0830182905261020083018290526102208301526102408201529051633b5000a960e21b81527378bfc8a7197abfb81d4774e7936a76092be2e1699063ed4002a490612f1a9030906004016143ab565b600060405180830381865af4158015612f37573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261082191908101906154b4565b6075546040805163c19d93fb60e01b815290516000926001600160a01b03169163c19d93fb9160048083019260209291908290030181865afa158015612fa9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082191906151ed565b60675460405163eaf6e48360e01b81526101009091046001600160a01b03169063eaf6e483906130019033906004016143ab565b602060405180830381865afa15801561301e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304291906150be565b15806130c257506075546040805163290a6c6560e11b8152905133926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa158015613092573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b69190614ea6565b6001600160a01b031614155b156130e0576040516369c7961360e01b815260040160405180910390fd5b6040516310a75da960e11b81526000907378bfc8a7197abfb81d4774e7936a76092be2e1699063214ebb529061311c9086908690600401614a5b565b602060405180830381865af4158015613139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315d9190614e59565b606a81905560698490554260735590506131756136aa565b505050565b6000613185606f5490565b612e4583670de0b6b3a7640000615131565b6074546040805163ca01302d60e01b815290516000926001600160a01b03169163ca01302d9160048083019260209291908290030181865afa158015610870573d6000803e3d6000fd5b6074546040516336dac81d60e21b81526000916001600160a01b03169063db6b2074906132129085906004016143ab565b602060405180830381865afa15801561322f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6a9190614e59565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b61328661435f565b606754604051637be53ca160e01b81526101009091046001600160a01b031690637be53ca1906132ba9033906004016143ab565b602060405180830381865afa1580156132d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132fb91906150be565b158061337b5750607554604080516303e1469160e61b8152905133926001600160a01b03169163f851a4409160048083019260209291908290030181865afa15801561334b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336f9190614ea6565b6001600160a01b031614155b156133985760405162b145b560e31b815260040160405180910390fd5b60745460405163de0c7fdf60e01b8152600481018490526001600160a01b039091169063de0c7fdf9060240160c0604051808303816000875af11580156133e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613407919061565a565b90508181608001516001600160a01b03167fb502f7ed5fc19e20b24f4956225e23e146e8a77cec046a4aef47739f9d2a0dfa83600001518460200151604051613451929190614a5b565b60405180910390a3613470816080015182600001518360200151613d19565b6020810151606e8054600090613487908490614e88565b9091555061349590506136aa565b919050565b6000610a6a8261317a565b6135066040518061012001604052806000815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b607560009054906101000a90046001600160a01b03166001600160a01b031663e06174e46040518163ffffffff1660e01b815260040161012060405180830381865afa15801561355a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108219190615676565b607654604080516338e2ad1b60e21b815290516060926001600160a01b03169163e38ab46c9160048083019260009291908290030181865afa1580156135c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261082191908101906156ff565b6075546040805163e40b858560e01b815290516000926001600160a01b03169163e40b85859160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b6000610a6a61035d836131e1565b607554604080516303e1469160e61b815290516000926001600160a01b03169163f851a4409160048083019260209291908290030181865afa158015610870573d6000803e3d6000fd5b6000611a698284615131565b6000611a69828461511d565b606760019054906101000a90046001600160a01b03166001600160a01b0316637a9bd5e46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156136fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137219190614ea6565b6001600160a01b0316631120d0bb306040518263ffffffff1660e01b815260040161374c91906143ab565b600060405180830381600087803b15801561376657600080fd5b505af1158015610f6a573d6000803e3d6000fd5b6001600160a01b0383166137dc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c5b565b6001600160a01b03821661383d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c5b565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0382166138f45760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610c5b565b61390060008383613d9a565b80603560008282546139129190614e88565b90915550506001600160a01b0382166000818152603360209081526040808320805486019055518481526000805160206158cc833981519152910160405180910390a35050565b6001600160a01b03163b151590565b600054610100900460ff1661398f5760405162461bcd60e51b8152600401610c5b90615733565b610fbd8282613f8e565b801580613a125750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906139cf903090869060040161538c565b602060405180830381865afa1580156139ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a109190614e59565b155b613a7d5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610c5b565b6040516001600160a01b03831660248201526044810182905261317590849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613fce565b6000613aec8484613253565b90506000198114610f6a5781811015613b475760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610c5b565b610f6a848484840361377a565b6001600160a01b038316613bb85760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c5b565b6001600160a01b038216613c1a5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c5b565b613c25838383613d9a565b6001600160a01b03831660009081526033602052604090205481811015613c9d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610c5b565b6001600160a01b0380851660008181526033602052604080822086860390559286168082529083902080548601905591516000805160206158cc83398151915290613ceb9086815260200190565b60405180910390a3610f6a565b610f6a846323b872dd60e01b858585604051602401613aa99392919061577e565b606854613d31906001600160a01b0316308584613cf8565b613d3b83836140a3565b826001600160a01b0316836001600160a01b0316846001600160a01b03167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db8486604051613d8a929190614a5b565b60405180910390a46131756136aa565b6001600160a01b03821615801590613dba57506001600160a01b03831615155b15613ef15760655460405163babcc53960e01b81526001600160a01b039091169063babcc53990613def9086906004016143ab565b602060405180830381865afa158015613e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e3091906150be565b1580613eaa575060655460405163babcc53960e01b81526001600160a01b039091169063babcc53990613e679085906004016143ab565b602060405180830381865afa158015613e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ea891906150be565b155b15613ec85760405163a24e573d60e01b815260040160405180910390fd5b80613ed2846131e1565b1015613ef15760405163a24e573d60e01b815260040160405180910390fd5b6001600160a01b03831615801590613f1157506001600160a01b03821615155b15613175576000613f2182610a43565b6074546040516315eaef6b60e01b81529192506001600160a01b0316906315eaef6b90613f569087908790869060040161577e565b600060405180830381600087803b158015613f7057600080fd5b505af1158015613f84573d6000803e3d6000fd5b5050505050505050565b600054610100900460ff16613fb55760405162461bcd60e51b8152600401610c5b90615733565b6036613fc183826157f0565b50603761317582826157f0565b6000614023826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166141d19092919063ffffffff16565b905080516000148061404457508080602001905181019061404491906150be565b6131755760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c5b565b6001600160a01b0382166141035760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c5b565b61410f82600083613d9a565b6001600160a01b038216600090815260336020526040902054818110156141835760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610c5b565b6001600160a01b03831660008181526033602090815260408083208686039055603580548790039055518581529192916000805160206158cc833981519152910160405180910390a3505050565b60606141e084846000856141e8565b949350505050565b6060824710156142495760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c5b565b600080866001600160a01b0316858760405161426591906158af565b60006040518083038185875af1925050503d80600081146142a2576040519150601f19603f3d011682016040523d82523d6000602084013e6142a7565b606091505b50915091506142b8878383876142c3565b979650505050505050565b60608315614330578251600003614329576142dd85613959565b6143295760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c5b565b50816141e0565b6141e083838151156143455781518083602001fd5b8060405162461bcd60e51b8152600401610c5b9190614571565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b600081518084526020808501945080840160005b838110156143f85781516001600160401b0316875295820195908201906001016143d3565b509495945050505050565b6020815261441560208201835161439e565b602082015160408201526040820151606082015260608201516080820152608082015160a082015260a082015160c082015260c082015160e0820152600060e08301516101008181850152808501519150506101208181850152808501519150506101408181850152808501519150506101608181850152808501519150506101808181850152808501519150506101a08181850152808501519150506101c08181850152808501519150506101e081818501528085015191505061020081818501528085015191505061026061022081818601526144f86102808601846143bf565b908601519092506102406145108682018360ff169052565b959095015193019290925250919050565b60005b8381101561453c578181015183820152602001614524565b50506000910152565b6000815180845261455d816020860160208601614521565b601f01601f19169290920160200192915050565b602081526000611a696020830184614545565b60006020828403121561459657600080fd5b5035919050565b6001600160a01b038116811461113e57600080fd5b80356134958161459d565b600080604083850312156145d057600080fd5b82356145db8161459d565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715614622576146226145e9565b60405290565b60405161010081016001600160401b0381118282101715614622576146226145e9565b60405161026081016001600160401b0381118282101715614622576146226145e9565b6040516101e081016001600160401b0381118282101715614622576146226145e9565b604051601f8201601f191681016001600160401b03811182821017156146b9576146b96145e9565b604052919050565b60006001600160401b038211156146da576146da6145e9565b5060051b60200190565b6001600160401b038116811461113e57600080fd5b6000602080838503121561470c57600080fd5b82356001600160401b0381111561472257600080fd5b8301601f8101851361473357600080fd5b8035614746614741826146c1565b614691565b81815260059190911b8201830190838101908783111561476557600080fd5b928401925b828410156142b857833561477d816146e4565b8252928401929084019061476a565b6000610120828403121561479f57600080fd5b6147a76145ff565b9050813581526147b9602083016145b2565b60208201526147ca604083016145b2565b6040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e082015261010080830135818301525092915050565b60006001600160401b0382111561482c5761482c6145e9565b50601f01601f191660200190565b600082601f83011261484b57600080fd5b813561485961474182614813565b81815284602083860101111561486e57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000808486036102608112156148a357600080fd5b610100808212156148b357600080fd5b6148bb614628565b915086356148c88161459d565b82526148d6602088016145b2565b60208301526148e7604088016145b2565b60408301526148f8606088016145b2565b6060830152614909608088016145b2565b608083015261491a60a088016145b2565b60a083015261492b60c088016145b2565b60c083015261493c60e088016145b2565b60e08301528195506149508882890161478c565b945050506102208501356001600160401b038082111561496f57600080fd5b61497b8883890161483a565b935061024087013591508082111561499257600080fd5b5061499f8782880161483a565b91505092959194509250565b600080604083850312156149be57600080fd5b50508035926020909101359150565b6000806000606084860312156149e257600080fd5b83356149ed8161459d565b925060208401356149fd8161459d565b929592945050506040919091013590565b600060208284031215614a2057600080fd5b8135611a698161459d565b60008060408385031215614a3e57600080fd5b823591506020830135614a508161459d565b809150509250929050565b918252602082015260400190565b805182526020808201519083015260408082015190830152606080820151908301526080808201516001600160a01b03169083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b81811015614aeb57614ad8838551614a69565b9284019260c09290920191600101614ac5565b50909695505050505050565b60006101e082019050614b0b82845161439e565b6020830151614b1d602084018261439e565b5060408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015181840152506101408084015181840152506101608084015181840152506101808084015181840152506101a08084015181840152506101c080840151818401525092915050565b634e487b7160e01b600052602160045260246000fd5b6020810160028310614bde57614bde614bb4565b91905290565b60208152614bf660208201835161439e565b602082015160408201526040820151606082015260608201516080820152608082015160a082015260a082015160c082015260c082015160e0820152600060e0830151610100614c488185018361439e565b8401519050610120614c5c8482018361439e565b8401519050610140614c708482018361439e565b8401519050610160614c848482018361439e565b8401519050610180614c988482018361439e565b808501519150506102606101a08181860152614cb8610280860184614545565b9250808601519050601f196101c0818786030181880152614cd98584614545565b9450808801519250506101e0614cf18188018461439e565b8701519150610200614d058782018461439e565b80880151925050610220828188015280880151925050610240818786030181880152614d3185846143bf565b94508088015192505050614d478286018261439e565b5090949350505050565b6020810160048310614bde57614bde614bb4565b60008060408385031215614d7857600080fd5b8235614d838161459d565b91506020830135614a508161459d565b60c08101610a6a8284614a69565b80518252602081015160018060a01b0380821660208501528060408401511660408501525050606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152505050565b6101208101610a6a8284614da1565b6020808252825182820181905260009190848201906040850190845b81811015614aeb5783516001600160401b031683529284019291840191600101614e34565b600060208284031215614e6b57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610a6a57610a6a614e72565b80516134958161459d565b600060208284031215614eb857600080fd5b8151611a698161459d565b600082601f830112614ed457600080fd5b81516020614ee4614741836146c1565b82815260059290921b84018101918181019086841115614f0357600080fd5b8286015b84811015614f27578051614f1a816146e4565b8352918301918301614f07565b509695505050505050565b805160ff8116811461349557600080fd5b600060208284031215614f5557600080fd5b81516001600160401b0380821115614f6c57600080fd5b908301906102608286031215614f8157600080fd5b614f8961464b565b614f9283614e9b565b81526020838101519082015260408084015190820152606080840151908201526080808401519082015260a0808401519082015260c0808401519082015260e08084015190820152610100808401519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a080840151908201526101c080840151908201526101e08084015190820152610200808401518381111561504657600080fd5b61505288828701614ec3565b8284015250506102209150615068828401614f32565b9181019190915261024091820151918101919091529392505050565b600181811c9082168061509857607f821691505b6020821081036150b857634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156150d057600080fd5b81518015158114611a6957600080fd5b634e487b7160e01b600052601260045260246000fd5b600082615105576151056150e0565b500690565b81810381811115610a6a57610a6a614e72565b60008261512c5761512c6150e0565b500490565b600081600019048311821515161561514b5761514b614e72565b500290565b60006001820161516257615162614e72565b5060010190565b6001600160a01b03868116825285811660208301528481166040830152831660608201526101a0810161519f6080830184614da1565b9695505050505050565b6001600160401b038281168282160390808211156151c9576151c9614e72565b5092915050565b6000602082840312156151e257600080fd5b8151611a69816146e4565b6000602082840312156151ff57600080fd5b815160048110611a6957600080fd5b600060c0828403121561522057600080fd5b60405160c081016001600160401b0381118282101715615242576152426145e9565b806040525080915082518152602083015160208201526040830151604082015260608301516060820152608083015161527a8161459d565b608082015260a092830151920191909152919050565b600060208083850312156152a357600080fd5b82516001600160401b038111156152b957600080fd5b8301601f810185136152ca57600080fd5b80516152d8614741826146c1565b81815260c091820283018401918482019190888411156152f757600080fd5b938501935b8385101561531d5761530e898661520e565b835293840193918501916152fc565b50979650505050505050565b634e487b7160e01b600052603260045260246000fd5b92835260208301919091526001600160a01b0316604082015260600190565b60008060006060848603121561537357600080fd5b8351925060208401519150604084015190509250925092565b6001600160a01b0392831681529116602082015260400190565b60006101e082840312156153b957600080fd5b6153c161466e565b6153ca83614e9b565b81526153d860208401614e9b565b602082015260408381015190820152606080840151908201526080808401519082015260a0808401519082015260c0808401519082015260e08084015190820152610100808401519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a080840151908201526101c0928301519281019290925250919050565b600082601f83011261548057600080fd5b815161548e61474182614813565b8181528460208386010111156154a357600080fd5b6141e0826020830160208701614521565b6000602082840312156154c657600080fd5b81516001600160401b03808211156154dd57600080fd5b9083019061026082860312156154f257600080fd5b6154fa61464b565b61550383614e9b565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261554d60e08401614e9b565b60e0820152610100615560818501614e9b565b90820152610120615572848201614e9b565b90820152610140615584848201614e9b565b90820152610160615596848201614e9b565b9082015261018083810151838111156155ae57600080fd5b6155ba8882870161546f565b8284015250506101a080840151838111156155d457600080fd5b6155e08882870161546f565b8284015250506101c06155f4818501614e9b565b908201526101e0615606848201614e9b565b908201526102008381015190820152610220808401518381111561562957600080fd5b61563588828701614ec3565b828401525050610240915061564b828401614e9b565b91810191909152949350505050565b600060c0828403121561566c57600080fd5b611a69838361520e565b6000610120828403121561568957600080fd5b6156916145ff565b825181526156a160208401614e9b565b60208201526156b260408401614e9b565b6040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b60006020828403121561571157600080fd5b81516001600160401b0381111561572757600080fd5b6141e084828501614ec3565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b601f82111561317557600081815260208120601f850160051c810160208610156157c95750805b601f850160051c820191505b818110156157e8578281556001016157d5565b505050505050565b81516001600160401b03811115615809576158096145e9565b61581d816158178454615084565b846157a2565b602080601f831160018114615852576000841561583a5750858301515b600019600386901b1c1916600185901b1785556157e8565b600085815260208120601f198616915b8281101561588157888601518255948401946001909101908401615862565b508582101561589f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600082516158c1818460208701614521565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212206a23daa415ff8c4e7e3e36a8949f30fc0ccb12f40cc45d529dd869c6d61a94ee64736f6c63430008100033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102f05760003560e01c806370a082311161018f57806370a0823114610515578063712577e21461052857806377c020a91461053057806378880710146105435780637c3a00fd1461055857806380bb521d146105605780638311fb62146105685780638456ec6e1461058857806394879a1c1461059957806395d89b41146105a1578063a0786081146105a9578063a3f8547714610636578063a457c2d714610649578063a9059cbb1461065c578063aa2f892d1461066f578063aa696ef814610682578063b1dd61b614610695578063b80945e9146106a8578063c19d93fb146106bd578063c2f39e7a146106d2578063c6e6f592146106e5578063ca01302d146106f8578063db6b207414610700578063dd62ed3e14610713578063de0c7fdf14610726578063def53cf314610746578063e06174e414610759578063e38ab46c1461076e578063e40b858514610783578063e5fc6d6d146102f5578063e8af8fa31461078b578063f851a4401461079e57600080fd5b806301e1d114146102f557806303210d3e1461031057806304bce9e61461032557806306fdde031461033a57806307a2d13a1461034f57806307cdb58a14610362578063095ea7b31461036c5780630b24697f1461038f5780631311b7bf146103a257806313b98c0f146102f557806316bc64f4146103b857806318160ddd146103cb5780631e0f9fd6146103d35780631f7bdb59146103e6578063214ebb52146103ee57806323b872dd14610401578063313ce56714610414578063384b54e91461042357806339509351146104365780633ba0b9a914610449578063402d267d1461045157806348a67aa9146104645780634aa9d585146104775780635214d8ca1461048a57806354fd4d5014610492578063597be6d1146104a257806359d5cd7b146104ab5780635d5366de146104be5780636d36daf0146104c65780636e3480b7146104d95780636e553f65146104e15780637058162314610502575b600080fd5b6102fd6107a6565b6040519081526020015b60405180910390f35b610318610826565b60405161030791906143ab565b61032d610894565b6040516103079190614403565b6103426109b1565b6040516103079190614571565b6102fd61035d366004614584565b610a43565b61036a610a70565b005b61037f61037a3660046145bd565b610f70565b6040519015158152602001610307565b61036a61039d3660046145bd565b610f88565b60675461010090046001600160a01b0316610318565b61036a6103c63660046146f9565b610fc1565b6035546102fd565b61036a6103e136600461488b565b611141565b6102fd61197e565b6102fd6103fc3660046149ab565b6119ec565b61037f61040f3660046149cd565b611a70565b60405160068152602001610307565b61036a610431366004614584565b611a94565b61037f6104443660046145bd565b611bec565b606f546102fd565b6102fd61045f366004614a0e565b611c0e565b61036a6104723660046149ab565b611d41565b607554610318906001600160a01b031681565b610318612017565b6040516101008152602001610307565b6102fd60775481565b6102fd6104b9366004614584565b612061565b6102fd61206c565b606554610318906001600160a01b031681565b6102fd6120b6565b6104f46104ef366004614a2b565b612100565b604051610307929190614a5b565b607454610318906001600160a01b031681565b6102fd610523366004614a0e565b612642565b6102fd61265d565b607654610318906001600160a01b031681565b61054b6126a7565b6040516103079190614aa9565b6069546102fd565b6102fd612719565b61057b610576366004614a0e565b612815565b6040516103079190614af7565b6068546001600160a01b0316610318565b61036a61291e565b610342612957565b6105b1612966565b6040516103079190600061016082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151818401525061014080840151818401525092915050565b61037f610644366004614a0e565b612a2c565b61037f6106573660046145bd565b612a9e565b61037f61066a3660046145bd565b612b19565b6102fd61067d366004614584565b612b27565b6102fd610690366004614584565b612e21565b60675460ff166040516103079190614bca565b6106b0612e4f565b6040516103079190614be4565b6106c5612f5f565b6040516103079190614d51565b61036a6106e03660046149ab565b612fcd565b6102fd6106f3366004614584565b61317a565b610318613197565b6102fd61070e366004614a0e565b6131e1565b6102fd610721366004614d65565b613253565b610739610734366004614584565b61327e565b6040516103079190614d93565b6102fd610754366004614584565b61349a565b6107616134a5565b6040516103079190614e09565b61077661357e565b6040516103079190614e18565b6102fd6135f0565b6102fd610799366004614a0e565b61363a565b610318613648565b6074546040805163f216a1a360e01b815290516000926001600160a01b03169163f216a1a39160048083019260209291908290030181865afa1580156107f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108149190614e59565b606b546108219190614e88565b905090565b60755460408051630190869f60e11b815290516000926001600160a01b0316916303210d3e9160048083019260209291908290030181865afa158015610870573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108219190614ea6565b61093560405180610260016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160608152602001600060ff168152602001600081525090565b60405163181021ed60e01b81527378bfc8a7197abfb81d4774e7936a76092be2e1699063181021ed9061096c9030906004016143ab565b600060405180830381865af4158015610989573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108219190810190614f43565b6060603680546109c090615084565b80601f01602080910402602001604051908101604052809291908181526020018280546109ec90615084565b8015610a395780601f10610a0e57610100808354040283529160200191610a39565b820191906000526020600020905b815481529060010190602001808311610a1c57829003601f168201915b5050505050905090565b6000610a6a670de0b6b3a7640000610a64610a5d606f5490565b8590613692565b9061369e565b92915050565b6067546040516250495760e01b81526101009091046001600160a01b0316906250495790610aa29033906004016143ab565b602060405180830381865afa158015610abf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae391906150be565b158015610b625750606754604051637be53ca160e01b81526101009091046001600160a01b031690637be53ca190610b1f9033906004016143ab565b602060405180830381865afa158015610b3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6091906150be565b155b15610b7f5760405162b145b560e31b815260040160405180910390fd5b6000610b8e62015180426150f6565b610b98904261510a565b9050607560009054906101000a90046001600160a01b03166001600160a01b0316635d5366de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c119190614e59565b610c1e62015180426150f6565b1015610c3457610c31620151808261510a565b90505b6070548111610c6457607054604051636692c96d60e11b8152610c5b918391600401614a5b565b60405180910390fd5b6070546000906201518090610c79908461510a565b610c83919061511d565b60705490915060005b82811015610ea757610ca18262015180614e88565b9150610cd4670de0b6b3a7640000610a64606960010154670de0b6b3a7640000610ccb9190614e88565b606f5490613692565b606f55606a54606b54600091670de0b6b3a764000091610cf49190615131565b610cfe919061511d565b90506000670de0b6b3a7640000607560009054906101000a90046001600160a01b03166001600160a01b03166362aada936040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d829190614e59565b606b54610d8f9190615131565b610d99919061511d565b90508160696002016000828254610db09190614e88565b9091555050606c8054839190600090610dca908490614e88565b909155505060718054829190600090610de4908490614e88565b909155505060728054829190600090610dfe908490614e88565b909155505060745460405163fe7eb29160e01b8152600481018690526000916001600160a01b03169063fe7eb291906024016020604051808303816000875af1158015610e4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e739190614e59565b90508060696002016000828254610e8a9190614e88565b925050819055505050508080610e9f90615150565b915050610c8c565b506000610eb762015180426150f6565b610ec1904261510a565b9050607560009054906101000a90046001600160a01b03166001600160a01b0316635d5366de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f3a9190614e59565b610f4762015180426150f6565b1015610f5d57610f5a620151808261510a565b90505b6070819055610f6a6136aa565b50505050565b600033610f7e81858561377a565b5060019392505050565b6074546001600160a01b03163314610fb35760405163a59decbf60e01b815260040160405180910390fd5b610fbd828261389e565b5050565b606754604051637be53ca160e01b81526101009091046001600160a01b031690637be53ca190610ff59033906004016143ab565b602060405180830381865afa158015611012573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103691906150be565b15806110b65750607554604080516303e1469160e61b8152905133926001600160a01b03169163f851a4409160048083019260209291908290030181865afa158015611086573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110aa9190614ea6565b6001600160a01b031614155b156110d35760405162b145b560e31b815260040160405180910390fd5b6110db6136aa565b6076546040516305af193d60e21b81526001600160a01b03909116906316bc64f49061110b908490600401614e18565b600060405180830381600087803b15801561112557600080fd5b505af1158015611139573d6000803e3d6000fd5b505050505b50565b600054610100900460ff16158080156111615750600054600160ff909116105b80611182575061117030613959565b158015611182575060005460ff166001145b6111e55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c5b565b6000805460ff191660011790558015611208576000805461ff0019166101001790555b6112128383613968565b60408501516067805460016001600160a01b039093166101000260ff19166001600160a81b03199091161791909117905560c0840151670de0b6b3a764000010806112635750620186a08460a00151115b8061127157508351620f4240115b806112865750835169d3c21bcecceda1000000105b8061129c575060208401516001600160a01b0316155b806112b2575060408401516001600160a01b0316155b806112c35750620151808460600151115b806112d45750620151808460800151115b806112e3575060058460e00151115b806112f357506005846101000151115b1561131157604051630fcf47e960e11b815260040160405180910390fd5b60a08401517378bfc8a7197abfb81d4774e7936a76092be2e1699063214ebb529061019061271061134a83670de0b6b3a7640000615131565b611354919061511d565b61135e919061511d565b6040518363ffffffff1660e01b815260040161137b929190614a5b565b602060405180830381865af4158015611398573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bc9190614e59565b60c08501526067546020860151604051637be53ca160e01b81526101009092046001600160a01b031691637be53ca1916113f8916004016143ab565b602060405180830381865afa158015611415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143991906150be565b61145657604051633006171960e21b815260040160405180910390fd5b8451606880546001600160a01b0319166001600160a01b0380841691909117909155608087015160408089015160208a015191516378f4eeeb60e01b815292909316936378f4eeeb936114b29330939192908b90600401615169565b6020604051808303816000875af11580156114d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f59190614ea6565b607580546001600160a01b0319166001600160a01b0392831617905560c08601516040516313db266360e31b8152911690639ed933189061153a9030906004016143ab565b6020604051808303816000875af1158015611559573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061157d9190614ea6565b606580546001600160a01b0319166001600160a01b0392831617905560e08601516040516313db266360e31b81526000929190911690639ed93318906115c79030906004016143ab565b6020604051808303816000875af11580156115e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160a9190614ea6565b607680546001600160a01b0319166001600160a01b038381169190911790915560755460408051632ea9b36f60e11b815290519394506000939190921691635d5366de9160048083019260209291908290030181865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116969190614e59565b6116a362015180426150f6565b101561173d576001600160a01b038216633c3cb08b6116c562015180426151a9565b6040516001600160e01b031960e084901b1681526001600160401b039091166004820152602401602060405180830381865afa158015611709573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172d91906151d0565b6001600160401b031690506117ba565b604051633c3cb08b60e01b81526001600160401b03421660048201526001600160a01b03831690633c3cb08b90602401602060405180830381865afa15801561178a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117ae91906151d0565b6001600160401b031690505b604080516101608101825260008082526020820181905281830181905260608083018290526080830182905260a0808401839052670de0b6b3a764000060c0850181905260e08501879052610100850184905261012085018490526101409094018390526069839055606a839055606b839055606c839055606d839055606e839055606f93909355607085905560718290556072829055607391909155890151908901518883015192516335bb74f560e11b81523060048201526001600160a01b03918216602482015292811660448401521690636b76e9ea906064016020604051808303816000875af11580156118b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118da9190614ea6565b607480546001600160a01b0319166001600160a01b03928316179055606854611907911630600019613999565b6040517f4196df5545177bff7cc5a8e7d409ae30d345a95b556b2eaf6b727038bef3128e90600090a150508015611139576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b60745460408051631f7bdb5960e01b815290516000926001600160a01b031691631f7bdb599160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108219190614e59565b6040516310a75da960e11b81526000907378bfc8a7197abfb81d4774e7936a76092be2e1699063214ebb5290611a289086908690600401614a5b565b602060405180830381865af4158015611a45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a699190614e59565b9392505050565b600033611a7e858285613ae0565b611a89858585613b54565b506001949350505050565b606754604051637be53ca160e01b81526101009091046001600160a01b031690637be53ca190611ac89033906004016143ab565b602060405180830381865afa158015611ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0991906150be565b1580611b895750607554604080516303e1469160e61b8152905133926001600160a01b03169163f851a4409160048083019260209291908290030181865afa158015611b59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7d9190614ea6565b6001600160a01b031614155b15611ba65760405162b145b560e31b815260040160405180910390fd5b607254811115611bc9576040516369f9a44760e11b815260040160405180910390fd5b8060696009016000828254611bde919061510a565b9091555061113e90506136aa565b600033610f7e818585611bff8383613253565b611c099190614e88565b61377a565b6000606760019054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c8791906150be565b151560011480611c9d5750611c9b82612a2c565b155b80611d2557506075546040805163c19d93fb60e01b815290516001926001600160a01b03169163c19d93fb9160048083019260209291908290030181865afa158015611ced573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1191906151ed565b6003811115611d2257611d22614bb4565b14155b15611d3257506000919050565b50670de0b6b3a7640000919050565b60675460405163eaf6e48360e01b81526101009091046001600160a01b03169063eaf6e48390611d759033906004016143ab565b602060405180830381865afa158015611d92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db691906150be565b1580611e3657506075546040805163290a6c6560e11b8152905133926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa158015611e06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2a9190614ea6565b6001600160a01b031614155b15611e54576040516369c7961360e01b815260040160405180910390fd5b60745460408051630788807160e41b815290516000926001600160a01b031691637888071091600480830192869291908290030181865afa158015611e9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611ec59190810190615290565b9050611ecf61435f565b6000805b8351811015611f335784848281518110611eef57611eef615329565b602002602001015160a0015103611f2157838181518110611f1257611f12615329565b60200260200101519250600191505b80611f2b81615150565b915050611ed3565b50801580611f445750848260200151115b15611f625760405163166877a960e21b815260040160405180910390fd5b607454604051624eb02760e41b8152600481018790526001600160a01b03909116906304eb027090602401600060405180830381600087803b158015611fa757600080fd5b505af1158015611fbb573d6000803e3d6000fd5b505050508382608001516001600160a01b03167f3732b90483b99a3d87ca37d7e421a92c5f07ce3a73a7738320da6ecac265720a84600001518560200151604051612007929190614a5b565b60405180910390a36111396136aa565b6075546040805163290a6c6560e11b815290516000926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa158015610870573d6000803e3d6000fd5b6000610a6a82610a43565b60755460408051632ea9b36f60e11b815290516000926001600160a01b031691635d5366de9160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b60755460408051636e3480b760e01b815290516000926001600160a01b031691636e3480b79160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b600080606760019054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612156573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217a91906150be565b151560010361219c5760405163146f5dc360e21b815260040160405180910390fd5b600180607560009054906101000a90046001600160a01b03166001600160a01b031663c19d93fb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221691906151ed565b600381111561222757612227614bb4565b14612245576040516367e554d160e01b815260040160405180910390fd5b60655460405163babcc53960e01b81526001600160a01b039091169063babcc539906122759033906004016143ab565b602060405180830381865afa158015612292573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b691906150be565b6122d357604051638c38000360e01b815260040160405180910390fd5b6075546040805163290a6c6560e11b8152905133926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa15801561231c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123409190614ea6565b6001600160a01b03160361236757604051638c38000360e01b815260040160405180910390fd5b6075546040805163c19d93fb60e01b815290516003926001600160a01b03169163c19d93fb9160048083019260209291908290030181865afa1580156123b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d591906151ed565b60038111156123e6576123e6614bb4565b14806123fb5750336001600160a01b03851614155b15612419576040516367e554d160e01b815260040160405180910390fd5b61242284611c0e565b8511156124505761243284611c0e565b8585604051632422a34560e11b8152600401610c5b9392919061533f565b8460000361247f5761246184611c0e565b858560405163203e505760e11b8152600401610c5b9392919061533f565b607454606f54606a5460405163ce88b43960e01b81526001600160a01b038881166004830152602482018a905260448201939093526064810191909152600092919091169063ce88b439906084016060604051808303816000875af11580156124ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612510919061535e565b606d805492975090955091925087919060009061252e908490614e88565b909155505060685461254b906001600160a01b0316333089613cf8565b612555858561389e565b61257530612561613197565b6068546001600160a01b0316919089613cf8565b607454604051632b907e9d60e01b8152600481018890526001600160a01b0390911690632b907e9d90602401600060405180830381600087803b1580156125bb57600080fd5b505af11580156125cf573d6000803e3d6000fd5b5050505080606960020160008282546125e89190614e88565b909155505060408051878152602081018690529081018490526001600160a01b038616907f0af19f929dc1d7b34887d6f1a7e36b8d6bc0a9071daf7f65d2bffff866683e739060600160405180910390a250509250929050565b6001600160a01b031660009081526033602052604090205490565b60755460408051633892bbf160e11b815290516000926001600160a01b03169163712577e29160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b60745460408051630788807160e41b815290516060926001600160a01b03169163788807109160048083019260009291908290030181865afa1580156126f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108219190810190615290565b60745460408051637329ef3960e11b815290516000926001600160a01b03169163e653de729160048083019260209291908290030181865afa158015612763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127879190614e59565b607460009054906101000a90046001600160a01b03166001600160a01b031663cd1032086040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127fe9190614e59565b60355461280b919061510a565b610821919061510a565b6128a0604051806101e0016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051636695bd3b60e01b81526000907378bfc8a7197abfb81d4774e7936a76092be2e16990636695bd3b906128dc903090879060040161538c565b6101e060405180830381865af41580156128fa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6991906153a6565b6075546001600160a01b031633146129495760405163300863cd60e01b815260040160405180910390fd5b6129516136aa565b42607755565b6060603780546109c090615084565b6129c360405180610160016040528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b5060408051610160810182526069548152606a546020820152606b5491810191909152606c546060820152606d546080820152606e5460a0820152606f5460c082015260705460e082015260715461010082015260725461012082015260735461014082015290565b60655460405163babcc53960e01b81526000916001600160a01b03169063babcc53990612a5d9085906004016143ab565b602060405180830381865afa158015612a7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6a91906150be565b60003381612aac8286613253565b905083811015612b0c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610c5b565b611a89828686840361377a565b600033610f7e818585613b54565b6000606760019054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba091906150be565b1515600103612bc25760405163146f5dc360e21b815260040160405180910390fd5b607754600003612be5576040516338c0a90160e11b815260040160405180910390fd5b60655460405163babcc53960e01b81526001600160a01b039091169063babcc53990612c159033906004016143ab565b602060405180830381865afa158015612c32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5691906150be565b612c7357604051638c38000360e01b815260040160405180910390fd5b6075546040805163290a6c6560e11b8152905133926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa158015612cbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce09190614ea6565b6001600160a01b031603612d0757604051638c38000360e01b815260040160405180910390fd5b6000612d1233612642565b11612d3057604051638c38000360e01b815260040160405180910390fd5b612d3982610a43565b606b54909150811115612d4b5750606b545b60745460405163014cf1e960e11b815233600482015260248101849052604481018390526001600160a01b0390911690630299e3d290606401600060405180830381600087803b158015612d9e57600080fd5b505af1158015612db2573d6000803e3d6000fd5b505050508060696002016000828254612dcb919061510a565b90915550612dd990506136aa565b336001600160a01b03167f58fe322fc5911ed072ec92f570e517b9793e350eb1ff7be0019fd9f3fade87bc8284604051612e14929190614a5b565b60405180910390a2919050565b606a54600090670de0b6b3a764000090612e3b9082614e88565b612e459084615131565b610a6a919061511d565b604080516102608101825260008082526020820181905281830181905260608083018290526080830182905260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018190526101a083018190526101c083018290526101e0830182905261020083018290526102208301526102408201529051633b5000a960e21b81527378bfc8a7197abfb81d4774e7936a76092be2e1699063ed4002a490612f1a9030906004016143ab565b600060405180830381865af4158015612f37573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261082191908101906154b4565b6075546040805163c19d93fb60e01b815290516000926001600160a01b03169163c19d93fb9160048083019260209291908290030181865afa158015612fa9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082191906151ed565b60675460405163eaf6e48360e01b81526101009091046001600160a01b03169063eaf6e483906130019033906004016143ab565b602060405180830381865afa15801561301e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304291906150be565b15806130c257506075546040805163290a6c6560e11b8152905133926001600160a01b031691635214d8ca9160048083019260209291908290030181865afa158015613092573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b69190614ea6565b6001600160a01b031614155b156130e0576040516369c7961360e01b815260040160405180910390fd5b6040516310a75da960e11b81526000907378bfc8a7197abfb81d4774e7936a76092be2e1699063214ebb529061311c9086908690600401614a5b565b602060405180830381865af4158015613139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315d9190614e59565b606a81905560698490554260735590506131756136aa565b505050565b6000613185606f5490565b612e4583670de0b6b3a7640000615131565b6074546040805163ca01302d60e01b815290516000926001600160a01b03169163ca01302d9160048083019260209291908290030181865afa158015610870573d6000803e3d6000fd5b6074546040516336dac81d60e21b81526000916001600160a01b03169063db6b2074906132129085906004016143ab565b602060405180830381865afa15801561322f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6a9190614e59565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b61328661435f565b606754604051637be53ca160e01b81526101009091046001600160a01b031690637be53ca1906132ba9033906004016143ab565b602060405180830381865afa1580156132d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132fb91906150be565b158061337b5750607554604080516303e1469160e61b8152905133926001600160a01b03169163f851a4409160048083019260209291908290030181865afa15801561334b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061336f9190614ea6565b6001600160a01b031614155b156133985760405162b145b560e31b815260040160405180910390fd5b60745460405163de0c7fdf60e01b8152600481018490526001600160a01b039091169063de0c7fdf9060240160c0604051808303816000875af11580156133e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613407919061565a565b90508181608001516001600160a01b03167fb502f7ed5fc19e20b24f4956225e23e146e8a77cec046a4aef47739f9d2a0dfa83600001518460200151604051613451929190614a5b565b60405180910390a3613470816080015182600001518360200151613d19565b6020810151606e8054600090613487908490614e88565b9091555061349590506136aa565b919050565b6000610a6a8261317a565b6135066040518061012001604052806000815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b607560009054906101000a90046001600160a01b03166001600160a01b031663e06174e46040518163ffffffff1660e01b815260040161012060405180830381865afa15801561355a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108219190615676565b607654604080516338e2ad1b60e21b815290516060926001600160a01b03169163e38ab46c9160048083019260009291908290030181865afa1580156135c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261082191908101906156ff565b6075546040805163e40b858560e01b815290516000926001600160a01b03169163e40b85859160048083019260209291908290030181865afa1580156119c8573d6000803e3d6000fd5b6000610a6a61035d836131e1565b607554604080516303e1469160e61b815290516000926001600160a01b03169163f851a4409160048083019260209291908290030181865afa158015610870573d6000803e3d6000fd5b6000611a698284615131565b6000611a69828461511d565b606760019054906101000a90046001600160a01b03166001600160a01b0316637a9bd5e46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156136fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137219190614ea6565b6001600160a01b0316631120d0bb306040518263ffffffff1660e01b815260040161374c91906143ab565b600060405180830381600087803b15801561376657600080fd5b505af1158015610f6a573d6000803e3d6000fd5b6001600160a01b0383166137dc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610c5b565b6001600160a01b03821661383d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610c5b565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0382166138f45760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610c5b565b61390060008383613d9a565b80603560008282546139129190614e88565b90915550506001600160a01b0382166000818152603360209081526040808320805486019055518481526000805160206158cc833981519152910160405180910390a35050565b6001600160a01b03163b151590565b600054610100900460ff1661398f5760405162461bcd60e51b8152600401610c5b90615733565b610fbd8282613f8e565b801580613a125750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906139cf903090869060040161538c565b602060405180830381865afa1580156139ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a109190614e59565b155b613a7d5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610c5b565b6040516001600160a01b03831660248201526044810182905261317590849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613fce565b6000613aec8484613253565b90506000198114610f6a5781811015613b475760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610c5b565b610f6a848484840361377a565b6001600160a01b038316613bb85760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610c5b565b6001600160a01b038216613c1a5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610c5b565b613c25838383613d9a565b6001600160a01b03831660009081526033602052604090205481811015613c9d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610c5b565b6001600160a01b0380851660008181526033602052604080822086860390559286168082529083902080548601905591516000805160206158cc83398151915290613ceb9086815260200190565b60405180910390a3610f6a565b610f6a846323b872dd60e01b858585604051602401613aa99392919061577e565b606854613d31906001600160a01b0316308584613cf8565b613d3b83836140a3565b826001600160a01b0316836001600160a01b0316846001600160a01b03167ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db8486604051613d8a929190614a5b565b60405180910390a46131756136aa565b6001600160a01b03821615801590613dba57506001600160a01b03831615155b15613ef15760655460405163babcc53960e01b81526001600160a01b039091169063babcc53990613def9086906004016143ab565b602060405180830381865afa158015613e0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e3091906150be565b1580613eaa575060655460405163babcc53960e01b81526001600160a01b039091169063babcc53990613e679085906004016143ab565b602060405180830381865afa158015613e84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ea891906150be565b155b15613ec85760405163a24e573d60e01b815260040160405180910390fd5b80613ed2846131e1565b1015613ef15760405163a24e573d60e01b815260040160405180910390fd5b6001600160a01b03831615801590613f1157506001600160a01b03821615155b15613175576000613f2182610a43565b6074546040516315eaef6b60e01b81529192506001600160a01b0316906315eaef6b90613f569087908790869060040161577e565b600060405180830381600087803b158015613f7057600080fd5b505af1158015613f84573d6000803e3d6000fd5b5050505050505050565b600054610100900460ff16613fb55760405162461bcd60e51b8152600401610c5b90615733565b6036613fc183826157f0565b50603761317582826157f0565b6000614023826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166141d19092919063ffffffff16565b905080516000148061404457508080602001905181019061404491906150be565b6131755760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c5b565b6001600160a01b0382166141035760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610c5b565b61410f82600083613d9a565b6001600160a01b038216600090815260336020526040902054818110156141835760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610c5b565b6001600160a01b03831660008181526033602090815260408083208686039055603580548790039055518581529192916000805160206158cc833981519152910160405180910390a3505050565b60606141e084846000856141e8565b949350505050565b6060824710156142495760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c5b565b600080866001600160a01b0316858760405161426591906158af565b60006040518083038185875af1925050503d80600081146142a2576040519150601f19603f3d011682016040523d82523d6000602084013e6142a7565b606091505b50915091506142b8878383876142c3565b979650505050505050565b60608315614330578251600003614329576142dd85613959565b6143295760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c5b565b50816141e0565b6141e083838151156143455781518083602001fd5b8060405162461bcd60e51b8152600401610c5b9190614571565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6001600160a01b03169052565b6001600160a01b0391909116815260200190565b600081518084526020808501945080840160005b838110156143f85781516001600160401b0316875295820195908201906001016143d3565b509495945050505050565b6020815261441560208201835161439e565b602082015160408201526040820151606082015260608201516080820152608082015160a082015260a082015160c082015260c082015160e0820152600060e08301516101008181850152808501519150506101208181850152808501519150506101408181850152808501519150506101608181850152808501519150506101808181850152808501519150506101a08181850152808501519150506101c08181850152808501519150506101e081818501528085015191505061020081818501528085015191505061026061022081818601526144f86102808601846143bf565b908601519092506102406145108682018360ff169052565b959095015193019290925250919050565b60005b8381101561453c578181015183820152602001614524565b50506000910152565b6000815180845261455d816020860160208601614521565b601f01601f19169290920160200192915050565b602081526000611a696020830184614545565b60006020828403121561459657600080fd5b5035919050565b6001600160a01b038116811461113e57600080fd5b80356134958161459d565b600080604083850312156145d057600080fd5b82356145db8161459d565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b0381118282101715614622576146226145e9565b60405290565b60405161010081016001600160401b0381118282101715614622576146226145e9565b60405161026081016001600160401b0381118282101715614622576146226145e9565b6040516101e081016001600160401b0381118282101715614622576146226145e9565b604051601f8201601f191681016001600160401b03811182821017156146b9576146b96145e9565b604052919050565b60006001600160401b038211156146da576146da6145e9565b5060051b60200190565b6001600160401b038116811461113e57600080fd5b6000602080838503121561470c57600080fd5b82356001600160401b0381111561472257600080fd5b8301601f8101851361473357600080fd5b8035614746614741826146c1565b614691565b81815260059190911b8201830190838101908783111561476557600080fd5b928401925b828410156142b857833561477d816146e4565b8252928401929084019061476a565b6000610120828403121561479f57600080fd5b6147a76145ff565b9050813581526147b9602083016145b2565b60208201526147ca604083016145b2565b6040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e082015261010080830135818301525092915050565b60006001600160401b0382111561482c5761482c6145e9565b50601f01601f191660200190565b600082601f83011261484b57600080fd5b813561485961474182614813565b81815284602083860101111561486e57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000808486036102608112156148a357600080fd5b610100808212156148b357600080fd5b6148bb614628565b915086356148c88161459d565b82526148d6602088016145b2565b60208301526148e7604088016145b2565b60408301526148f8606088016145b2565b6060830152614909608088016145b2565b608083015261491a60a088016145b2565b60a083015261492b60c088016145b2565b60c083015261493c60e088016145b2565b60e08301528195506149508882890161478c565b945050506102208501356001600160401b038082111561496f57600080fd5b61497b8883890161483a565b935061024087013591508082111561499257600080fd5b5061499f8782880161483a565b91505092959194509250565b600080604083850312156149be57600080fd5b50508035926020909101359150565b6000806000606084860312156149e257600080fd5b83356149ed8161459d565b925060208401356149fd8161459d565b929592945050506040919091013590565b600060208284031215614a2057600080fd5b8135611a698161459d565b60008060408385031215614a3e57600080fd5b823591506020830135614a508161459d565b809150509250929050565b918252602082015260400190565b805182526020808201519083015260408082015190830152606080820151908301526080808201516001600160a01b03169083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b81811015614aeb57614ad8838551614a69565b9284019260c09290920191600101614ac5565b50909695505050505050565b60006101e082019050614b0b82845161439e565b6020830151614b1d602084018261439e565b5060408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015181840152506101408084015181840152506101608084015181840152506101808084015181840152506101a08084015181840152506101c080840151818401525092915050565b634e487b7160e01b600052602160045260246000fd5b6020810160028310614bde57614bde614bb4565b91905290565b60208152614bf660208201835161439e565b602082015160408201526040820151606082015260608201516080820152608082015160a082015260a082015160c082015260c082015160e0820152600060e0830151610100614c488185018361439e565b8401519050610120614c5c8482018361439e565b8401519050610140614c708482018361439e565b8401519050610160614c848482018361439e565b8401519050610180614c988482018361439e565b808501519150506102606101a08181860152614cb8610280860184614545565b9250808601519050601f196101c0818786030181880152614cd98584614545565b9450808801519250506101e0614cf18188018461439e565b8701519150610200614d058782018461439e565b80880151925050610220828188015280880151925050610240818786030181880152614d3185846143bf565b94508088015192505050614d478286018261439e565b5090949350505050565b6020810160048310614bde57614bde614bb4565b60008060408385031215614d7857600080fd5b8235614d838161459d565b91506020830135614a508161459d565b60c08101610a6a8284614a69565b80518252602081015160018060a01b0380821660208501528060408401511660408501525050606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e08301526101008082015181840152505050565b6101208101610a6a8284614da1565b6020808252825182820181905260009190848201906040850190845b81811015614aeb5783516001600160401b031683529284019291840191600101614e34565b600060208284031215614e6b57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610a6a57610a6a614e72565b80516134958161459d565b600060208284031215614eb857600080fd5b8151611a698161459d565b600082601f830112614ed457600080fd5b81516020614ee4614741836146c1565b82815260059290921b84018101918181019086841115614f0357600080fd5b8286015b84811015614f27578051614f1a816146e4565b8352918301918301614f07565b509695505050505050565b805160ff8116811461349557600080fd5b600060208284031215614f5557600080fd5b81516001600160401b0380821115614f6c57600080fd5b908301906102608286031215614f8157600080fd5b614f8961464b565b614f9283614e9b565b81526020838101519082015260408084015190820152606080840151908201526080808401519082015260a0808401519082015260c0808401519082015260e08084015190820152610100808401519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a080840151908201526101c080840151908201526101e08084015190820152610200808401518381111561504657600080fd5b61505288828701614ec3565b8284015250506102209150615068828401614f32565b9181019190915261024091820151918101919091529392505050565b600181811c9082168061509857607f821691505b6020821081036150b857634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156150d057600080fd5b81518015158114611a6957600080fd5b634e487b7160e01b600052601260045260246000fd5b600082615105576151056150e0565b500690565b81810381811115610a6a57610a6a614e72565b60008261512c5761512c6150e0565b500490565b600081600019048311821515161561514b5761514b614e72565b500290565b60006001820161516257615162614e72565b5060010190565b6001600160a01b03868116825285811660208301528481166040830152831660608201526101a0810161519f6080830184614da1565b9695505050505050565b6001600160401b038281168282160390808211156151c9576151c9614e72565b5092915050565b6000602082840312156151e257600080fd5b8151611a69816146e4565b6000602082840312156151ff57600080fd5b815160048110611a6957600080fd5b600060c0828403121561522057600080fd5b60405160c081016001600160401b0381118282101715615242576152426145e9565b806040525080915082518152602083015160208201526040830151604082015260608301516060820152608083015161527a8161459d565b608082015260a092830151920191909152919050565b600060208083850312156152a357600080fd5b82516001600160401b038111156152b957600080fd5b8301601f810185136152ca57600080fd5b80516152d8614741826146c1565b81815260c091820283018401918482019190888411156152f757600080fd5b938501935b8385101561531d5761530e898661520e565b835293840193918501916152fc565b50979650505050505050565b634e487b7160e01b600052603260045260246000fd5b92835260208301919091526001600160a01b0316604082015260600190565b60008060006060848603121561537357600080fd5b8351925060208401519150604084015190509250925092565b6001600160a01b0392831681529116602082015260400190565b60006101e082840312156153b957600080fd5b6153c161466e565b6153ca83614e9b565b81526153d860208401614e9b565b602082015260408381015190820152606080840151908201526080808401519082015260a0808401519082015260c0808401519082015260e08084015190820152610100808401519082015261012080840151908201526101408084015190820152610160808401519082015261018080840151908201526101a080840151908201526101c0928301519281019290925250919050565b600082601f83011261548057600080fd5b815161548e61474182614813565b8181528460208386010111156154a357600080fd5b6141e0826020830160208701614521565b6000602082840312156154c657600080fd5b81516001600160401b03808211156154dd57600080fd5b9083019061026082860312156154f257600080fd5b6154fa61464b565b61550383614e9b565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261554d60e08401614e9b565b60e0820152610100615560818501614e9b565b90820152610120615572848201614e9b565b90820152610140615584848201614e9b565b90820152610160615596848201614e9b565b9082015261018083810151838111156155ae57600080fd5b6155ba8882870161546f565b8284015250506101a080840151838111156155d457600080fd5b6155e08882870161546f565b8284015250506101c06155f4818501614e9b565b908201526101e0615606848201614e9b565b908201526102008381015190820152610220808401518381111561562957600080fd5b61563588828701614ec3565b828401525050610240915061564b828401614e9b565b91810191909152949350505050565b600060c0828403121561566c57600080fd5b611a69838361520e565b6000610120828403121561568957600080fd5b6156916145ff565b825181526156a160208401614e9b565b60208201526156b260408401614e9b565b6040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b60006020828403121561571157600080fd5b81516001600160401b0381111561572757600080fd5b6141e084828501614ec3565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b601f82111561317557600081815260208120601f850160051c810160208610156157c95750805b601f850160051c820191505b818110156157e8578281556001016157d5565b505050505050565b81516001600160401b03811115615809576158096145e9565b61581d816158178454615084565b846157a2565b602080601f831160018114615852576000841561583a5750858301515b600019600386901b1c1916600185901b1785556157e8565b600085815260208120601f198616915b8281101561588157888601518255948401946001909101908401615862565b508582101561589f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b600082516158c1818460208701614521565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212206a23daa415ff8c4e7e3e36a8949f30fc0ccb12f40cc45d529dd869c6d61a94ee64736f6c63430008100033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.