Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,221 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Add Collateral | 11445283 | 14 secs ago | IN | 0 S | 0.05958372 | ||||
Vault Deposit Ad... | 11444780 | 3 mins ago | IN | 0 S | 0.00726665 | ||||
Vault Deposit Ad... | 11441465 | 23 mins ago | IN | 0 S | 0.00705859 | ||||
Vault Deposit Ad... | 11441082 | 26 mins ago | IN | 0 S | 0.00726665 | ||||
Remove Collatera... | 11440848 | 27 mins ago | IN | 0 S | 0.01035425 | ||||
Vault Deposit Ad... | 11439835 | 34 mins ago | IN | 0 S | 0.00705859 | ||||
Vault Deposit Ad... | 11437436 | 49 mins ago | IN | 0 S | 0.01666104 | ||||
Vault Deposit Ad... | 11436299 | 56 mins ago | IN | 0 S | 0.0085514 | ||||
Vault Deposit Ad... | 11436112 | 57 mins ago | IN | 0 S | 0.01805622 | ||||
Remove Collatera... | 11435729 | 1 hr ago | IN | 0 S | 0.0130515 | ||||
Vault Deposit Ad... | 11435147 | 1 hr ago | IN | 0 S | 0.00799097 | ||||
Vault Deposit Ad... | 11435091 | 1 hr ago | IN | 0 S | 0.00685399 | ||||
Remove Collatera... | 11434763 | 1 hr ago | IN | 0 S | 0.01118094 | ||||
Vault Deposit Ad... | 11433644 | 1 hr ago | IN | 0 S | 0.00770698 | ||||
Vault Deposit Ad... | 11432726 | 1 hr ago | IN | 0 S | 0.00770028 | ||||
Vault Deposit Ad... | 11431094 | 1 hr ago | IN | 0 S | 0.00907814 | ||||
Vault Deposit Ad... | 11430663 | 1 hr ago | IN | 0 S | 0.01805769 | ||||
Vault Deposit Ad... | 11429503 | 1 hr ago | IN | 0 S | 0.00671797 | ||||
Vault Deposit Ad... | 11428604 | 1 hr ago | IN | 0 S | 0.00751811 | ||||
Vault Deposit Ad... | 11427451 | 1 hr ago | IN | 0 S | 0.00671797 | ||||
Vault Deposit Ad... | 11426587 | 1 hr ago | IN | 0 S | 0.00840642 | ||||
Vault Deposit Ad... | 11426042 | 2 hrs ago | IN | 0 S | 0.01580481 | ||||
Vault Deposit Ad... | 11424934 | 2 hrs ago | IN | 0 S | 0.01580176 | ||||
Vault Deposit Ad... | 11424607 | 2 hrs ago | IN | 0 S | 0.01242377 | ||||
Vault Deposit Ad... | 11423668 | 2 hrs ago | IN | 0 S | 0.00833052 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Lender
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {Ownable} from "./abstract/Ownable.sol"; import {ReentrancyGuard} from "./abstract/ReentrancyGuard.sol"; import {Rebase, AuxRebase} from "./library/AuxRebase.sol"; import {IBaseContracts} from "./interface/IBaseContracts.sol"; import {IDUSXProvider} from "./interface/IDUSXProvider.sol"; import {IERC20Custom} from "./interface/IERC20Custom.sol"; import {IERC20Token} from "./interface/IERC20Token.sol"; import {IFeesWithdrawer} from "./interface/IFees.sol"; import {ILenderOwner} from "./interface/ILenderOwner.sol"; import {IMiscHelper} from "./interface/IMiscHelper.sol"; import {IOracle} from "./interface/IOracle.sol"; import {IVault} from "./interface/IVault.sol"; /** * @title Lender * @dev Core lending contract managing collateralized borrowing * @notice Handles lending operations, collateral management, and liquidations with: * · Collateralized borrowing * · Dynamic interest rates * · Liquidation mechanisms * · Fee management */ contract Lender is Ownable, ReentrancyGuard { using AuxRebase for Rebase; /// @notice Structs for managing accrual info and borrow caps struct AccrueInfo { uint256 lastAccrued; uint256 feesEarned; uint256 interestPerSecond; } struct BorrowCap { uint256 total; uint256 borrowPartPerAddress; } /// @notice Core state variables AccrueInfo public accrueInfo; BorrowCap public borrowLimit; Rebase public totalBorrow; uint256 public collateralRatio; uint256 public exchangeRate; uint256 public liquidationMultiplier; uint256 public totalCollateralShare; uint256 public immutable collateralPrecision; uint256 public constant HUNDREDK_PRECISION = 100_000; uint256 public constant MANTISSA_ONE = 1e18; uint256 internal constant LIQUIDATION_FEE = 10; uint256 internal constant LIQUIDATION_FEE_PRECISION = 100; /// @notice Protocol contracts IDUSXProvider public immutable dusxProvider; IFeesWithdrawer public immutable feesWithdrawer; IERC20Custom public immutable collateral; IERC20Token public immutable dusx; IMiscHelper public helper; IOracle public immutable oracle; IVault public immutable vault; address public feeTo; mapping(address => uint256) public userBorrowPart; mapping(address => uint256) public userCollateralShare; /// @notice Events event Accrued(uint256 accruedAmount); event BorrowLimitChanged(uint256 newLimit, uint256 perAddressPart); event ExchangeRateChanged(uint256 rate); event FeesWithdrawn(address indexed feeTo, uint256 feesEarnedFraction); event InterestRateChanged(uint256 oldInterestRate, uint256 newInterestRate); event CollateralAdded( address indexed from, address indexed to, uint256 share ); event CollateralRemoved( address indexed from, address indexed to, uint256 share ); event Borrowed( address indexed from, address indexed to, uint256 amount, uint256 part ); event Repaid( address indexed from, address indexed to, uint256 amount, uint256 part ); event LiquidationExecuted( address indexed user, address indexed to, uint256 collateralShare, uint256 borrowAmount, uint256 borrowPart ); /// @dev Custom errors error AllSolvent(); error BorrowLimitExceeded(); error ExchangeRateNotUpdated(); error InvalidParameter(); error InvalidSkim(); error UserInsolvent(); error ZeroAddress(); modifier solvent(address msgSender) { _; uint256 _exchangeRate = _updateExchangeRate(); if (!_isSolvent(msgSender, _exchangeRate)) { revert UserInsolvent(); } } modifier onlyHelper() { if (address(helper) != _msgSender()) { revert UnauthorizedAccount(_msgSender()); } _; } /** * @notice Initializes the lending contract * @param baseContracts_ BaseContracts instance for protocol integration * @param collateral_ Collateral token address * @param collateralRatio_ Initial collateral ratio * @param liquidationMultiplier_ Initial liquidation multiplier */ constructor( IBaseContracts baseContracts_, IERC20Custom collateral_, uint256 collateralRatio_, uint256 liquidationMultiplier_ ) { _ensureNonzeroAddress(address(baseContracts_)); _ensureNonzeroAddress(address(collateral_)); collateral = collateral_; // Get immutable contracts from BaseContracts vault = baseContracts_.vault(); dusx = baseContracts_.dusx(); dusxProvider = baseContracts_.dusxProvider(); feesWithdrawer = baseContracts_.feesWithdrawer(); helper = baseContracts_.helper(); ILenderOwner lenderOwner = baseContracts_.lenderOwner(); // Validate addresses _ensureNonzeroAddress(address(vault)); _ensureNonzeroAddress(address(dusx)); _ensureNonzeroAddress(address(dusxProvider)); _ensureNonzeroAddress(address(feesWithdrawer)); _ensureNonzeroAddress(address(helper)); _ensureNonzeroAddress(address(lenderOwner)); // Set oracle based on collateral type IOracle oracle_; if (address(collateral_) == address(baseContracts_.veSTTX())) { oracle_ = baseContracts_.oracleFloorPrice(); } else { oracle_ = baseContracts_.oracleChainlink(); } _ensureNonzeroAddress(address(oracle_)); oracle = oracle_; // Initialize contract state transferOwnership(address(lenderOwner)); uint8 decimals_ = collateral_.decimals(); if (decimals_ > 18) { revert InvalidParameter(); } collateralPrecision = 10 ** decimals_; feeTo = address(feesWithdrawer); collateralRatio = collateralRatio_; liquidationMultiplier = liquidationMultiplier_; accrueInfo.interestPerSecond = 316880879; borrowLimit = BorrowCap(0, 0); exchangeRate = oracle.getPrice(address(collateral)); _accrue(); } function updateExchangeRate() external nonReentrant { _updateExchangeRate(); } function vaultDepositAddCollateral( uint256 amount ) external payable nonReentrant { uint256 share = vault.toShare(collateral, amount, false); userCollateralShare[_msgSender()] += share; uint256 oldTotalCollateralShare = totalCollateralShare; totalCollateralShare = oldTotalCollateralShare + share; vault.deposit(collateral, _msgSender(), _msgSender(), amount, 0); _addTokens(collateral, share, oldTotalCollateralShare, false); _afterAddCollateral(_msgSender(), share); emit CollateralAdded(_msgSender(), _msgSender(), share); } function changeBorrowLimit( uint256 newBorrowLimit, uint256 borrowPartPerAddress ) external onlyOwner { borrowLimit = BorrowCap(newBorrowLimit, borrowPartPerAddress); emit BorrowLimitChanged(newBorrowLimit, borrowPartPerAddress); } function changeInterestRate(uint256 newInterestRate) external onlyOwner { uint256 oldInterestRate = accrueInfo.interestPerSecond; _accrue(); accrueInfo.interestPerSecond = newInterestRate; emit InterestRateChanged(oldInterestRate, newInterestRate); } // Core lending functions function accrue() external nonReentrant { _accrue(); } function borrowVaultWithdraw( address msgSender, uint256 amount ) external nonReentrant solvent(msgSender) onlyHelper returns (uint256 part, uint256 share) { _accrue(); (part, share) = _borrow(msgSender, amount); uint256 maxAmount = vault.toAmount( dusx, vault.balanceOf(dusx, msgSender), false ); amount = maxAmount > amount ? amount : maxAmount; vault.withdraw(dusx, msgSender, msgSender, amount, 0); } function removeCollateralVaultWithdraw( uint256 amount ) external nonReentrant solvent(_msgSender()) { uint256 share = vault.toShare(collateral, amount, false); _accrue(); _removeCollateral(_msgSender(), share); vault.withdraw(collateral, _msgSender(), _msgSender(), 0, share); } // User operations function addCollateral( address to, bool skim, uint256 share ) external nonReentrant { userCollateralShare[to] += share; uint256 oldTotalCollateralShare = totalCollateralShare; totalCollateralShare = oldTotalCollateralShare + share; _addTokens(collateral, share, oldTotalCollateralShare, skim); _afterAddCollateral(to, share); emit CollateralAdded(skim ? address(vault) : _msgSender(), to, share); } function removeCollateral( address to, uint256 share ) external nonReentrant solvent(_msgSender()) { _accrue(); _removeCollateral(to, share); } function borrow( address msgSender, uint256 amount ) external nonReentrant solvent(msgSender) onlyHelper returns (uint256 part, uint256 share) { _accrue(); (part, share) = _borrow(msgSender, amount); } function repay( address payer, address to, bool skim, uint256 part ) external nonReentrant onlyHelper returns (uint256 amount) { _accrue(); (totalBorrow, amount) = totalBorrow.sub(part, true); if (part > userBorrowPart[to]) { part = userBorrowPart[to]; } userBorrowPart[to] -= part; uint256 share = vault.toShare(dusx, amount, true); vault.transfer( dusx, skim ? address(vault) : payer, address(this), share ); emit Repaid(skim ? address(vault) : payer, to, amount, part); } function liquidate( address liquidator, address[] memory users, uint256[] memory maxBorrowParts, address to ) external nonReentrant onlyHelper { uint256 _exchangeRate = _updateExchangeRate(); _accrue(); uint256 allCollateralShare = 0; uint256 allBorrowAmount = 0; uint256 allBorrowPart = 0; Rebase memory vaultTotals = vault.totals(collateral); _beforeUsersLiquidated(users, maxBorrowParts); uint256 length = users.length; for (uint256 i; i < length; i++) { address user = users[i]; if (!_isSolvent(user, _exchangeRate)) { uint256 borrowPart; uint256 availableBorrowPart = userBorrowPart[user]; borrowPart = maxBorrowParts[i] > availableBorrowPart ? availableBorrowPart : maxBorrowParts[i]; uint256 borrowAmount = totalBorrow.toElastic(borrowPart, false); uint256 collateralShare = vaultTotals.toBase( (borrowAmount * liquidationMultiplier * collateralPrecision) / _exchangeRate / HUNDREDK_PRECISION, false ); _beforeUserLiquidated( user, borrowPart, borrowAmount, collateralShare ); userBorrowPart[user] = availableBorrowPart - borrowPart; userCollateralShare[user] -= collateralShare; _afterUserLiquidated(user, collateralShare); emit CollateralRemoved(user, to, collateralShare); emit Repaid(liquidator, user, borrowAmount, borrowPart); emit LiquidationExecuted( user, to, collateralShare, borrowAmount, borrowPart ); allCollateralShare += collateralShare; allBorrowAmount += borrowAmount; allBorrowPart += borrowPart; } } if (allBorrowAmount == 0) { revert AllSolvent(); } totalBorrow.elastic -= allBorrowAmount; totalBorrow.base -= allBorrowPart; totalCollateralShare -= allCollateralShare; { uint256 liquidationFee = ((((allBorrowAmount * liquidationMultiplier) / HUNDREDK_PRECISION) - allBorrowAmount) * LIQUIDATION_FEE) / LIQUIDATION_FEE_PRECISION; allBorrowAmount += liquidationFee; accrueInfo.feesEarned += liquidationFee; } uint256 allBorrowShare = vault.toShare(dusx, allBorrowAmount, true); vault.transfer(dusx, liquidator, address(this), allBorrowShare); vault.transfer(collateral, address(this), to, allCollateralShare); } function withdrawFees(uint256 amountToProvide) external nonReentrant { if (_msgSender() != address(feesWithdrawer)) revert UnauthorizedAccount(_msgSender()); _accrue(); uint256 _feesEarned = accrueInfo.feesEarned; uint256 share = vault.toShare(dusx, _feesEarned, false); accrueInfo.feesEarned = 0; dusxProvider.provide(amountToProvide); vault.transfer(dusx, address(this), feeTo, share); emit FeesWithdrawn(feeTo, _feesEarned); } function isSolvent(address user) external view returns (bool) { return _isSolvent(user, exchangeRate); } function _afterAddCollateral( address user, uint256 collateralShare ) internal virtual {} function _afterRemoveCollateral( address from, address to, uint256 collateralShare ) internal virtual {} function _preBorrowAction( address to, uint256 amount, uint256 newBorrowPart, uint256 part ) internal virtual {} function _beforeUsersLiquidated( address[] memory users, uint256[] memory maxBorrowPart ) internal virtual {} function _beforeUserLiquidated( address user, uint256 borrowPart, uint256 borrowAmount, uint256 collateralShare ) internal virtual {} function _afterUserLiquidated( address user, uint256 collateralShare ) internal virtual {} function _accrue() private { AccrueInfo memory _accrueInfo = accrueInfo; uint256 elapsedTime = block.timestamp - _accrueInfo.lastAccrued; if (elapsedTime == 0) return; Rebase memory _totalBorrow = totalBorrow; if (_totalBorrow.base == 0) { _accrueInfo.lastAccrued = block.timestamp; accrueInfo = _accrueInfo; return; } uint256 extraAmount = (_totalBorrow.elastic * _accrueInfo.interestPerSecond * elapsedTime) / MANTISSA_ONE; _totalBorrow.elastic += extraAmount; totalBorrow = _totalBorrow; _accrueInfo.feesEarned += extraAmount; _accrueInfo.lastAccrued = block.timestamp; accrueInfo = _accrueInfo; emit Accrued(extraAmount); } function _addTokens( IERC20Custom token, uint256 share, uint256 total, bool skim ) private { if (skim) { if (share > vault.balanceOf(token, address(this)) - total) { revert InvalidSkim(); } } else { vault.transfer(token, _msgSender(), address(this), share); } } function _removeCollateral(address to, uint256 share) private { userCollateralShare[_msgSender()] -= share; totalCollateralShare -= share; _afterRemoveCollateral(_msgSender(), to, share); emit CollateralRemoved(_msgSender(), to, share); vault.transfer(collateral, address(this), to, share); } function _borrow( address to, uint256 amount ) private returns (uint256 part, uint256 share) { (totalBorrow, part) = totalBorrow.add(amount, true); BorrowCap memory cap = borrowLimit; if (totalBorrow.elastic > cap.total) { revert BorrowLimitExceeded(); } uint256 newBorrowPart = userBorrowPart[to] + part; if (newBorrowPart > cap.borrowPartPerAddress) { revert BorrowLimitExceeded(); } _preBorrowAction(to, amount, newBorrowPart, part); userBorrowPart[to] = newBorrowPart; uint256 lenderDUSXAmount = vault.toAmount( dusx, vault.balanceOf(dusx, address(this)), false ); uint256 amountToProvide; if (amount > lenderDUSXAmount) { amountToProvide = amount - lenderDUSXAmount; } else { amountToProvide = 0; } dusxProvider.provide(amountToProvide); share = vault.toShare(dusx, amount, false); vault.transfer(dusx, address(this), to, share); emit Borrowed(to, to, amount, part); } function _updateExchangeRate() private returns (uint256) { uint256 newExchangeRate = oracle.getPrice(address(collateral)); if (newExchangeRate == 0) revert ExchangeRateNotUpdated(); exchangeRate = newExchangeRate; emit ExchangeRateChanged(newExchangeRate); return exchangeRate; } function _isSolvent( address user, uint256 exchangeRate_ ) private view returns (bool) { uint256 borrowPart = userBorrowPart[user]; uint256 collateralShare = userCollateralShare[user]; if (borrowPart == 0) { return true; } else if (collateralShare == 0) { return false; } else { Rebase memory _totalBorrow = totalBorrow; return vault.toAmount( collateral, (collateralShare * collateralRatio) / HUNDREDK_PRECISION, false ) >= (borrowPart * _totalBorrow.elastic * collateralPrecision) / _totalBorrow.base / exchangeRate_; } } // Validates that an address is not zero function _ensureNonzeroAddress(address addr) private pure { if (addr == address(0)) { revert ZeroAddress(); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title Context * @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, as 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). * @notice This contract is used through inheritance. It will make available the * modifier `_msgSender()`, which can be used to reference the account that * called a function within an implementing contract. */ abstract contract Context { /*////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Gets the sender of the current call * @dev Provides a way to retrieve the message sender that supports meta-transactions * @return Sender address (msg.sender in the base implementation) */ function _msgSender() internal view virtual returns (address) { return msg.sender; } /** * @notice Gets the complete calldata of the current call * @dev Provides a way to retrieve the message data that supports meta-transactions * @return Complete calldata bytes */ function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @notice Gets the length of any context-specific suffix in the message data * @dev Used in meta-transaction implementations to account for additional data * @return Length of the context suffix (0 in the base implementation) */ function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {Context} from "./Context.sol"; /** * @title Ownable * @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. * @notice By default, the owner account will be the one that deploys the contract. * This can later be changed with {transferOwnership} and {renounceOwnership}. */ abstract contract Ownable is Context { /*////////////////////////////////////////////////////////////// STATE VARIABLES //////////////////////////////////////////////////////////////*/ /// @notice Address of the current owner address private _owner; /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ /// @notice Emitted when ownership is transferred event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /*////////////////////////////////////////////////////////////// CUSTOM ERRORS //////////////////////////////////////////////////////////////*/ /// @notice Thrown when non-owner tries to call owner-only function error UnauthorizedAccount(address account); /// @notice Thrown when trying to transfer ownership to invalid address error InvalidOwner(address owner); /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ /** * @dev Throws if called by any account other than the owner */ modifier onlyOwner() { _checkOwner(); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /** * @dev Initializes the contract setting the deployer as the initial owner */ constructor() { _transferOwnership(_msgSender()); } /*////////////////////////////////////////////////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Leaves the contract without owner * @dev Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @notice Transfers ownership of the contract to a new account * @dev The new owner cannot be the zero address * @param newOwner The address that will become the new owner */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert InvalidOwner(address(0)); } _transferOwnership(newOwner); } /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Returns the address of the current owner * @return Current owner address */ function owner() public view virtual returns (address) { return _owner; } /*////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @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 Throws if the sender is not the owner */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert UnauthorizedAccount(_msgSender()); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title ReentrancyGuard * @dev Contract module that helps prevent reentrant calls to a function * @notice This module is used through inheritance. It will make available the modifier * `nonReentrant`, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. */ abstract contract ReentrancyGuard { /*////////////////////////////////////////////////////////////// STATE VARIABLES //////////////////////////////////////////////////////////////*/ /// @notice Guard state constants uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; /// @notice Current state of the guard uint256 private _status; /*////////////////////////////////////////////////////////////// CUSTOM ERRORS //////////////////////////////////////////////////////////////*/ error ReentrantCall(); /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ /** * @notice Initializes the contract by setting the initial reentrancy guard state */ constructor() { _status = NOT_ENTERED; } /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Checks if a protected function is currently executing * @return True if the contract is in the entered state */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } /*////////////////////////////////////////////////////////////// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @dev Sets guard state before protected function execution * @notice Reverts if a reentrant call is detected */ function _nonReentrantBefore() private { if (_status == ENTERED) { revert ReentrantCall(); } _status = ENTERED; } /** * @dev Resets guard state after protected function execution */ function _nonReentrantAfter() private { _status = NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IDUSXProvider} from "./IDUSXProvider.sol"; import {IERC20Token} from "./IERC20Token.sol"; import {IERC20TokenRebase} from "./IERC20TokenRebase.sol"; import {IFeesDistributor} from "./IFees.sol"; import {IFeesWithdrawer} from "./IFees.sol"; import {IFloor} from "./IFloor.sol"; import {ILenderOwner} from "./ILenderOwner.sol"; import {ILiquidationHelper} from "./ILiquidationHelper.sol"; import {IMarketLens} from "./IMarketLens.sol"; import {IMiscHelper} from "./IMiscHelper.sol"; import {IOracle} from "./IOracle.sol"; import {IPSM} from "./IPSM.sol"; import {IRepayHelper} from "./IRepayHelper.sol"; import {IStableOwner} from "./IStableOwner.sol"; import {IStakedDUSX} from "./IStakedDUSX.sol"; import {ISupplyHangingCalculator} from "./ISupplyHangingCalculator.sol"; import {IVault} from "./IVault.sol"; import {IVoteEscrowedSTTX} from "./IVoteEscrowedSTTX.sol"; import {IDynamicInterestRate} from "./IDynamicInterestRate.sol"; import {IMinter} from "./IMinter.sol"; interface IBaseContracts { struct CoreTokens { IERC20Token dusx; IERC20TokenRebase sttx; IStakedDUSX stDUSX; IVoteEscrowedSTTX veSTTX; } struct PSMContracts { IPSM psmCircle; IPSM psmTether; IStableOwner stableOwner; } struct OracleContracts { IOracle oracleChainlink; IOracle oracleFloorPrice; } struct HelperContracts { IMiscHelper helper; ILiquidationHelper liquidationHelper; IRepayHelper repayHelper; IMarketLens marketLens; } error ZeroAddress(); error ContractAlreadySet(); // Struct getters function coreTokens() external view returns (CoreTokens memory); function psmContracts() external view returns (PSMContracts memory); function oracleContracts() external view returns (OracleContracts memory); function helperContracts() external view returns (HelperContracts memory); // Individual contract getters function dusxProvider() external view returns (IDUSXProvider); function feesDistributor() external view returns (IFeesDistributor); function feesWithdrawer() external view returns (IFeesWithdrawer); function floor() external view returns (IFloor); function lenderOwner() external view returns (ILenderOwner); function minter() external view returns (IMinter); function supplyCalculator() external view returns (ISupplyHangingCalculator); function vault() external view returns (IVault); function dynamicInterestRate() external view returns (IDynamicInterestRate); // Convenience getters for struct members function dusx() external view returns (IERC20Token); function sttx() external view returns (IERC20TokenRebase); function stDUSX() external view returns (IStakedDUSX); function veSTTX() external view returns (IVoteEscrowedSTTX); function psmCircle() external view returns (IPSM); function psmTether() external view returns (IPSM); function stableOwner() external view returns (IStableOwner); function oracleChainlink() external view returns (IOracle); function oracleFloorPrice() external view returns (IOracle); function helper() external view returns (IMiscHelper); function liquidationHelper() external view returns (ILiquidationHelper); function repayHelper() external view returns (IRepayHelper); function marketLens() external view returns (IMarketLens); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title IDUSXProvider * @dev Interface for DUSX token provision and distribution operations * @notice Defines functionality for: * 1. Token provision management * 2. Supply control * 3. Distribution tracking */ interface IDUSXProvider { /*////////////////////////////////////////////////////////////// PROVISION OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Provides DUSX tokens to the requesting address * @param amount The quantity of DUSX tokens to provide in base units * @dev Handles: * · Token minting/transfer * · Supply tracking * · State updates * * Requirements: * · Caller is authorized * · Amount > 0 * · Within supply limits * * Effects: * · Increases recipient balance * · Updates total supply * · Emits provision event */ function provide(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title IDynamicInterestRate * @dev Interface for dynamic interest rate calculations in the lending protocol * @notice Defines methods for retrieving time-based interest rates that: * 1. Adjust based on market conditions * 2. Support per-second and base rate calculations * 3. Maintain precision through proper scaling * * This interface is crucial for: * · Accurate interest accrual * · Dynamic market response * · Protocol yield calculations */ interface IDynamicInterestRate { /*////////////////////////////////////////////////////////////// INTEREST RATE QUERIES //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves the current interest rate per second * @return uint256 Interest rate per second, scaled by 1e18 * @dev Used for precise interest calculations over time periods */ function getInterestPerSecond() external view returns (uint256); /** * @notice Retrieves the current base interest rate * @return uint256 Base interest rate, scaled by 1e18 * @dev Represents the foundational rate before adjustments */ function getInterestRate() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title IERC20Custom * @dev Interface for the ERC20 fungible token standard (EIP-20) * @notice Defines functionality for: * 1. Token transfers * 2. Allowance management * 3. Balance tracking * 4. Token metadata */ interface IERC20Custom { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ /** * @dev Emitted on token transfer between addresses * @param from Source address (0x0 for mints) * @param to Destination address (0x0 for burns) * @param value Amount of tokens transferred * @notice Tracks: * · Regular transfers * · Minting operations * · Burning operations */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when spending allowance is granted * @param owner Address granting permission * @param spender Address receiving permission * @param value Amount of tokens approved * @notice Records: * · New approvals * · Updated allowances * · Revoked permissions */ event Approval( address indexed owner, address indexed spender, uint256 value ); /*////////////////////////////////////////////////////////////// TRANSFER OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Transfers tokens to specified recipient * @param to Recipient address * @param value Amount to transfer in base units * @return bool True if transfer succeeds * @dev Requirements: * · Caller has sufficient balance * · Recipient is valid * · Amount > 0 * * Effects: * · Decreases caller balance * · Increases recipient balance * · Emits Transfer event */ function transfer(address to, uint256 value) external returns (bool); /** * @notice Executes transfer on behalf of token owner * @param from Source address * @param to Destination address * @param value Amount to transfer in base units * @return bool True if transfer succeeds * @dev Requirements: * · Caller has sufficient allowance * · Source has sufficient balance * · Valid addresses * * Effects: * · Decreases allowance * · Updates balances * · Emits Transfer event */ function transferFrom( address from, address to, uint256 value ) external returns (bool); /*////////////////////////////////////////////////////////////// APPROVAL OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Authorizes address to spend tokens * @param spender Address to authorize * @param value Amount to authorize in base units * @return bool True if approval succeeds * @dev Controls: * · Spending permissions * · Delegation limits * · Authorization levels * * Security: * · Overwrites previous allowance * · Requires explicit value * · Emits Approval event */ function approve(address spender, uint256 value) external returns (bool); /*////////////////////////////////////////////////////////////// TOKEN METADATA //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves human-readable token name * @return string Full token name */ function name() external view returns (string memory); /** * @notice Retrieves token trading symbol * @return string Short token identifier */ function symbol() external view returns (string memory); /** * @notice Retrieves token decimal precision * @return uint8 Number of decimal places * @dev Standard: * · 18 for most tokens * · Used for display formatting */ function decimals() external view returns (uint8); /*////////////////////////////////////////////////////////////// BALANCE QUERIES //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves total token supply * @return uint256 Current total supply * @dev Reflects: * · All minted tokens * · Minus burned tokens * · In base units */ function totalSupply() external view returns (uint256); /** * @notice Retrieves account token balance * @param account Address to query * @return uint256 Current balance in base units * @dev Returns: * · Available balance * · Includes pending rewards * · Excludes locked tokens */ function balanceOf(address account) external view returns (uint256); /** * @notice Retrieves remaining spending allowance * @param owner Token owner address * @param spender Authorized spender address * @return uint256 Current allowance in base units * @dev Shows: * · Approved amount * · Remaining limit * · Delegation status */ function allowance( address owner, address spender ) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IERC20Custom} from "./IERC20Custom.sol"; /** * @title IERC20Token * @dev Extended interface for ERC20 tokens with supply control capabilities * @notice Defines functionality for: * 1. Token minting * 2. Token burning * 3. Supply management */ interface IERC20Token is IERC20Custom { /*////////////////////////////////////////////////////////////// SUPPLY MANAGEMENT //////////////////////////////////////////////////////////////*/ /** * @notice Mints new tokens to specified account * @param account Address to receive minted tokens * @param amount Quantity of tokens to mint in base units * @dev Controls: * · Supply expansion * · Balance updates * · Event emission * * Requirements: * · Caller is authorized * · Within maxSupply * · Valid recipient */ function mint(address account, uint256 amount) external; /** * @notice Burns tokens from specified account * @param account Address to burn tokens from * @param amount Quantity of tokens to burn in base units * @dev Manages: * · Supply reduction * · Balance updates * · Event emission * * Requirements: * · Caller is authorized * · Sufficient balance * · Amount > 0 */ function burn(address account, uint256 amount) external; /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves maximum token supply limit * @return uint256 Maximum supply cap in base units * @dev Enforces: * · Supply ceiling * · Mint restrictions * · Protocol limits * * Note: This is an immutable value that * cannot be exceeded by minting operations */ function maxSupply() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IERC20Custom} from "./IERC20Custom.sol"; /** * @title IERC20TokenRebase * @dev Extended interface for ERC20 tokens with elastic supply and safe management * @notice Defines functionality for: * 1. Supply elasticity (rebasing) * 2. Safe-based token management * 3. Supply control mechanisms * 4. Configuration management */ interface IERC20TokenRebase is IERC20Custom { /*////////////////////////////////////////////////////////////// SUPPLY MANAGEMENT //////////////////////////////////////////////////////////////*/ /** * @notice Mints new tokens to specified account * @param account Address to receive minted tokens * @param amount Quantity of tokens to mint in base units * @dev Requires: * · Caller is authorized minter * · Within maxSupply limits * · Valid recipient */ function mint(address account, uint256 amount) external; /** * @notice Burns tokens from specified account * @param account Address to burn tokens from * @param amount Quantity of tokens to burn in base units * @dev Requires: * · Caller is authorized * · Account has sufficient balance * · Amount > 0 */ function burn(address account, uint256 amount) external; /*////////////////////////////////////////////////////////////// REBASE OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Executes supply rebase based on current parameters * @dev Triggers: * · Supply adjustment * · Balance recalculation * · Event emission * * Considers: * · Rebase interval * · Basis points * · Supply limits */ function rebase() external; /** * @notice Configures rebase parameters * @param rebaseInterval Time period between rebases (in seconds) * @param rebaseBasisPoints Scale factor for rebase (in basis points) * @dev Controls: * · Rebase frequency * · Rebase magnitude * · Supply elasticity */ function setRebaseConfig( uint256 rebaseInterval, uint256 rebaseBasisPoints ) external; /*////////////////////////////////////////////////////////////// SAFE MANAGEMENT //////////////////////////////////////////////////////////////*/ /** * @notice Initializes new token management safe * @param safe Address of safe to create * @dev Establishes: * · Safe permissions * · Access controls * · Management capabilities */ function createSafe(address safe) external; /** * @notice Removes existing token management safe * @param safe Address of safe to remove * @dev Handles: * · Permission revocation * · State cleanup * · Access termination */ function destroySafe(address safe) external; /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves floor contract address * @return address Active floor contract * @dev Used for: * · Price stability * · Supply control */ function floor() external view returns (address); /** * @notice Retrieves authorized minter address * @return address Active minter contract * @dev Controls: * · Mint permissions * · Supply expansion */ function minter() external view returns (address); /** * @notice Returns absolute maximum token supply * @return uint256 Maximum supply cap in base units * @dev Enforces: * · Hard supply limit * · Mint restrictions */ function maxSupply() external view returns (uint256); /** * @notice Calculates maximum supply after rebase * @return uint256 Post-rebase maximum supply in base units * @dev Considers: * · Current max supply * · Rebase parameters * · Supply caps */ function maxSupplyRebased() external view returns (uint256); /** * @notice Calculates total supply after rebase * @return uint256 Post-rebase total supply in base units * @dev Reflects: * · Current supply * · Rebase effects * · Supply limits */ function totalSupplyRebased() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title IFeesWithdrawer * @dev Interface for protocol fee withdrawal operations * @notice Defines functionality for: * 1. Secure fee withdrawal * 2. Access control for withdrawals * 3. Protocol revenue management * * This interface ensures: * · Controlled access to protocol fees * · Safe transfer of accumulated revenue * · Proper accounting of withdrawn amounts */ interface IFeesWithdrawer { /*////////////////////////////////////////////////////////////// WITHDRAWAL OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Withdraws accumulated protocol fees to designated recipients * @dev Only callable by authorized withdrawers * Handles: * · Fee accounting updates * · Transfer of tokens * · Event emission for tracking */ function withdraw() external; } /** * @title IFeesDistributor * @dev Interface for protocol fee distribution and allocation * @notice Defines functionality for: * 1. Fee distribution across protocol components * 2. Dynamic allocation management * 3. Floor token revenue sharing * * This interface manages: * · Revenue distribution logic * · Allocation percentages * · Protocol incentive mechanisms */ interface IFeesDistributor { /*////////////////////////////////////////////////////////////// DISTRIBUTION OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Distributes accumulated protocol fees according to set allocations * @dev Handles the distribution of fees to: * · Floor token stakers * · Protocol treasury * · Other designated recipients */ function distribute() external; /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Returns current percentage allocated to Floor token stakers * @return uint256 Floor allocation percentage, scaled by 1e18 */ function floorAllocation() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title IFloor * @dev Interface for protocol floor price management and capital operations * @notice Defines functionality for: * 1. Token deposit management * 2. Refund processing * 3. Capital tracking */ interface IFloor { /*////////////////////////////////////////////////////////////// DEPOSIT OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Processes token deposits into the floor contract * @param msgSender Address initiating the deposit * @param amount Quantity of tokens to deposit * @dev Handles: * · Token transfer validation * · Capital tracking updates * · Event emission */ function deposit(address msgSender, uint256 amount) external; /*////////////////////////////////////////////////////////////// REFUND OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Processes token refunds from the floor contract * @param msgSender Address receiving the refund * @param amount Quantity of tokens to refund * @dev Ensures: * · Sufficient contract balance * · Authorized withdrawal * · Capital accounting */ function refund(address msgSender, uint256 amount) external; /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Returns current total capital held in the floor contract * @return uint256 Current capital amount in base units * @dev Used for: * · Floor price calculations * · Protocol health metrics * · Capital adequacy checks */ function capital() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {Rebase} from "../library/AuxRebase.sol"; import {IERC20Custom} from "./IERC20Custom.sol"; import {IOracle} from "./IOracle.sol"; import {IVault} from "./IVault.sol"; /** * @title ILender * @dev Interface for lending operations and management * @notice Defines the core lending protocol functionality including: * 1. Collateral management and borrowing operations * 2. Interest rate and fee management * 3. Liquidation handling * 4. Vault integration * * The interface is designed to support: * · Over-collateralized lending * · Dynamic interest rates * · Liquidation mechanisms * · Fee collection and distribution */ interface ILender { /*////////////////////////////////////////////////////////////// ADMIN CONFIGURATION //////////////////////////////////////////////////////////////*/ /** * @notice Updates the interest rate for borrowing * @param newInterestRate New interest rate (scaled by 1e18) */ function changeInterestRate(uint256 newInterestRate) external; /** * @notice Sets global and per-address borrowing limits * @param newBorrowLimit Total borrowing limit for the protocol * @param perAddressPart Maximum borrow amount per address */ function changeBorrowLimit( uint256 newBorrowLimit, uint256 perAddressPart ) external; /*////////////////////////////////////////////////////////////// CORE LENDING OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Updates protocol state with accrued interest */ function accrue() external; /** * @notice Updates the exchange rate from the oracle */ function updateExchangeRate() external; /** * @notice Withdraws accumulated protocol fees * @param amountToProvide Amount of fees to withdraw */ function withdrawFees(uint256 amountToProvide) external; /*////////////////////////////////////////////////////////////// LIQUIDATION HANDLING //////////////////////////////////////////////////////////////*/ /** * @notice Liquidates undercollateralized positions * @param liquidator Address performing the liquidation * @param users Array of user addresses to liquidate * @param maxBorrowParts Maximum borrow parts to liquidate per user * @param to Address to receive liquidated collateral */ function liquidate( address liquidator, address[] memory users, uint256[] memory maxBorrowParts, address to ) external; /*////////////////////////////////////////////////////////////// VAULT OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Deposits collateral into the vault * @param amount Amount of collateral to deposit */ function vaultDepositAddCollateral(uint256 amount) external; /** * @notice Withdraws borrowed assets from the vault * @param msgSender Address initiating the withdrawal * @param amount Amount to withdraw * @return part Borrow part assigned * @return share Share of the vault */ function borrowVaultWithdraw( address msgSender, uint256 amount ) external returns (uint256 part, uint256 share); /*////////////////////////////////////////////////////////////// COLLATERAL MANAGEMENT //////////////////////////////////////////////////////////////*/ /** * @notice Adds collateral to a lending position * @param to Address to credit the collateral * @param skim True to skim tokens from the contract * @param share Amount of shares to add as collateral */ function addCollateral(address to, bool skim, uint256 share) external; /** * @notice Removes collateral from a lending position * @param to Address to receive the removed collateral * @param share Amount of shares to remove */ function removeCollateral(address to, uint256 share) external; /*////////////////////////////////////////////////////////////// BORROWING OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Borrows assets against deposited collateral * @param msgSender Address initiating the borrow * @param amount Amount to borrow * @return part Borrow part assigned * @return share Share of the borrowed amount */ function borrow( address msgSender, uint256 amount ) external returns (uint256 part, uint256 share); /** * @notice Repays borrowed assets * @param payer Address paying the debt * @param to Address whose debt to repay * @param skim True to skim tokens from the contract * @param part Amount of borrow part to repay * @return amount Actual amount repaid */ function repay( address payer, address to, bool skim, uint256 part ) external returns (uint256 amount); /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Gets the oracle contract address * @return IOracle Oracle interface */ function oracle() external view returns (IOracle); /** * @notice Gets interest accrual information * @return Last accrual timestamp, accumulated interest, interest per second */ function accrueInfo() external view returns (uint256, uint256, uint256); /** * @notice Gets the required collateral ratio * @return uint256 Collateral ratio (scaled by 1e5) */ function collateralRatio() external view returns (uint256); /** * @notice Gets the liquidation bonus multiplier * @return uint256 Liquidation multiplier (scaled by 1e5) */ function liquidationMultiplier() external view returns (uint256); /** * @notice Gets total collateral shares in the protocol * @return uint256 Total collateral share amount */ function totalCollateralShare() external view returns (uint256); /** * @notice Gets the vault contract address * @return IVault Vault interface */ function vault() external view returns (IVault); /** * @notice Gets the fee recipient address * @return address Fee recipient */ function feeTo() external view returns (address); /** * @notice Gets the collateral token address * @return IERC20Custom Collateral token interface */ function collateral() external view returns (IERC20Custom); /** * @notice Gets total borrow state * @return Rebase Total borrow information */ function totalBorrow() external view returns (Rebase memory); /** * @notice Gets user's borrow part * @param account User address * @return uint256 User's borrow part */ function userBorrowPart(address account) external view returns (uint256); /** * @notice Gets user's collateral share * @param account User address * @return uint256 User's collateral share */ function userCollateralShare( address account ) external view returns (uint256); /** * @notice Gets protocol borrowing limits * @return total Total protocol borrow limit * @return borrowPartPerAddress Per-address borrow limit */ function borrowLimit() external view returns (uint256 total, uint256 borrowPartPerAddress); /** * @notice Gets the DUSX token address * @return IERC20Custom DUSX token interface */ function dusx() external view returns (IERC20Custom); /** * @notice Gets all accounts with active positions * @return address[] Array of account addresses */ function accounts() external view returns (address[] memory); /** * @notice Gets the collateral precision factor * @return uint256 Collateral precision */ function collateralPrecision() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {ILender} from "./ILender.sol"; /** * @title ILenderOwner * @dev Interface for protocol-level lender management and configuration * @notice Defines functionality for: * 1. Interest rate management * 2. Borrow limit control * 3. Risk parameter adjustment */ interface ILenderOwner { /*////////////////////////////////////////////////////////////// INTEREST MANAGEMENT //////////////////////////////////////////////////////////////*/ /** * @notice Updates lender's interest rate configuration * @param lender The lender contract to modify * @param newInterestRate New interest rate value in basis points * @dev Controls: * · Interest accrual * · Yield generation * · Protocol revenue * * Requirements: * · Caller is authorized * · Rate within bounds * · Valid lender contract */ function changeInterestRate( ILender lender, uint256 newInterestRate ) external; /*////////////////////////////////////////////////////////////// LIMIT MANAGEMENT //////////////////////////////////////////////////////////////*/ /** * @notice Updates lender's borrowing constraints * @param lender The lender contract to modify * @param newBorrowLimit New total protocol borrow limit * @param perAddressPart Maximum borrow limit per address * @dev Manages: * · Protocol exposure * · Individual limits * · Risk thresholds * * Requirements: * · Caller is authorized * · Valid limits * · perAddressPart <= newBorrowLimit * * Security: * · Prevents overleveraging * · Controls risk exposure * · Ensures protocol stability */ function changeBorrowLimit( ILender lender, uint256 newBorrowLimit, uint256 perAddressPart ) external; /*////////////////////////////////////////////////////////////// DEPRECATION MANAGEMENT //////////////////////////////////////////////////////////////*/ /** * @notice Checks if a lender contract is deprecated * @param lender The lender address to check * @return bool True if the lender is deprecated, false otherwise * @dev Used to: * · Prevent operations on deprecated markets * · Control market lifecycle * · Manage protocol upgrades * * Security: * · Read-only function * · No state modifications * · Access control not required */ function deprecated(address lender) external view returns (bool); /** * @notice Checks if a lender contract is in manual mode * @param lender The lender address to check * @return bool True if the lender is in manual mode, false otherwise * @dev Used to: * · Determine if borrow limits are managed manually * · Control automatic interest rate adjustments * * Security: * · Read-only function * · No state modifications * · Access control not required */ function manual(address lender) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IERC20Custom} from "./IERC20Custom.sol"; import {ILender} from "../interface/ILender.sol"; import {IMiscHelper} from "../interface/IMiscHelper.sol"; /** * @title ILiquidationHelper * @dev Interface for liquidation assistance operations * @notice Defines comprehensive liquidation functionality including: * 1. Direct liquidation execution * 2. Liquidation amount calculations * 3. Position health checks * 4. Preview and simulation functions * * The helper provides: * · Maximum and partial liquidation support * · Customizable recipient addresses * · Pre-execution liquidation simulations * · Automated DUSX amount calculations */ interface ILiquidationHelper { /*////////////////////////////////////////////////////////////// CONFIGURATION //////////////////////////////////////////////////////////////*/ /*////////////////////////////////////////////////////////////// LIQUIDATION EXECUTION //////////////////////////////////////////////////////////////*/ /** * @notice Liquidates maximum possible amount for an account * @param lender Address of the lending contract * @param account Address to be liquidated * @return collateralAmount Amount of collateral received * @return adjustedBorrowPart Adjusted borrow amount after liquidation * @return requiredDUSXAmount DUSX tokens needed to execute liquidation * @dev Automatically calculates maximum liquidatable amount */ function liquidateMax( ILender lender, address account ) external returns ( uint256 collateralAmount, uint256 adjustedBorrowPart, uint256 requiredDUSXAmount ); /** * @notice Liquidates specific amount for an account * @param lender Address of the lending contract * @param account Address to be liquidated * @param borrowPart Amount of borrow position to liquidate * @return collateralAmount Amount of collateral received * @return adjustedBorrowPart Adjusted borrow amount after liquidation * @return requiredDUSXAmount DUSX tokens needed to execute liquidation * @dev Validates borrowPart against maximum liquidatable amount */ function liquidate( ILender lender, address account, uint256 borrowPart ) external returns ( uint256 collateralAmount, uint256 adjustedBorrowPart, uint256 requiredDUSXAmount ); /*////////////////////////////////////////////////////////////// LIQUIDATION WITH CUSTOM RECIPIENT //////////////////////////////////////////////////////////////*/ /** * @notice Liquidates maximum amount and sends to specified recipient * @param lender Address of the lending contract * @param account Address to be liquidated * @param recipient Address to receive liquidated assets * @dev Combines max liquidation with custom recipient */ function liquidateMaxTo( ILender lender, address account, address recipient ) external; /** * @notice Liquidates specific amount and sends to specified recipient * @param lender Address of the lending contract * @param account Address to be liquidated * @param recipient Address to receive liquidated assets * @param borrowPart Amount of borrow position to liquidate * @dev Combines partial liquidation with custom recipient */ function liquidateTo( ILender lender, address account, address recipient, uint256 borrowPart ) external; /*////////////////////////////////////////////////////////////// LIQUIDATION PREVIEWS //////////////////////////////////////////////////////////////*/ /** * @notice Previews maximum possible liquidation amounts * @param lender Address of the lending contract * @param account Address to check * @return liquidatable Whether the account can be liquidated * @return requiredDUSXAmount DUSX tokens needed for liquidation * @return adjustedBorrowPart Final borrow amount after liquidation * @return returnedCollateralAmount Collateral amount to be received * @dev Simulates liquidation without executing */ function previewMaxLiquidation( ILender lender, address account ) external view returns ( bool liquidatable, uint256 requiredDUSXAmount, uint256 adjustedBorrowPart, uint256 returnedCollateralAmount ); /** * @notice Previews specific liquidation amounts * @param lender Address of the lending contract * @param account Address to check * @param borrowPart Amount of borrow position to liquidate * @return liquidatable Whether the account can be liquidated * @return requiredDUSXAmount DUSX tokens needed for liquidation * @return adjustedBorrowPart Final borrow amount after liquidation * @return returnedCollateralAmount Collateral amount to be received * @dev Simulates partial liquidation without executing */ function previewLiquidation( ILender lender, address account, uint256 borrowPart ) external view returns ( bool liquidatable, uint256 requiredDUSXAmount, uint256 adjustedBorrowPart, uint256 returnedCollateralAmount ); /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Checks if an account is eligible for liquidation * @param lender Address of the lending contract * @param account Address to check * @return bool True if account can be liquidated * @dev Considers collateral ratio and position health */ function isLiquidatable( ILender lender, address account ) external view returns (bool); /** * @notice Returns the DUSX token contract used for liquidations * @return IERC20Custom DUSX token interface * @dev DUSX is required to execute liquidations */ function dusx() external view returns (IERC20Custom); /** * @notice Returns the helper utility contract * @return IMiscHelper Helper interface for additional functions * @dev Helper provides supporting calculations and checks */ function helper() external view returns (IMiscHelper); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {ILender} from "./ILender.sol"; /** * @title IMarketLens * @dev Interface for viewing and analyzing lending market data * @notice Provides functionality for: * 1. Market size analysis * 2. Borrowing metrics * 3. Risk assessment data */ interface IMarketLens { /*////////////////////////////////////////////////////////////// MARKET METRICS //////////////////////////////////////////////////////////////*/ /** * @notice Calculates total borrowed amount from a specific lending market * @param lender Address of the lending market to analyze * @return uint256 Total borrowed amount in base units * @dev Aggregates: * · Active loan positions * · Accrued interest * · Pending liquidations * * Used for: * · Market size analysis * · Risk assessment * · Protocol health monitoring */ function getTotalBorrowed(ILender lender) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IERC20Custom} from "./IERC20Custom.sol"; /** * @title IMinter * @dev Interface for the Minter contract */ interface IMinter { /** * @notice Enables whitelist minting phase */ function enableWhitelistMint() external; /** * @notice Enables public minting phase */ function enablePublicMint() external; /** * @notice Adds a wallet to the whitelist * @param wallet Wallet address to whitelist */ function addToWhitelist(address wallet) external; /** * @notice Mints tokens during whitelist phase * @param stablecoin Stablecoin used for minting * @param stableAmount Amount of stablecoin to mint against */ function whitelistMint( IERC20Custom stablecoin, uint256 stableAmount ) external; /** * @notice Mints tokens during public phase * @param stablecoin Stablecoin used for minting * @param stableAmount Amount of stablecoin to mint against */ function publicMint(IERC20Custom stablecoin, uint256 stableAmount) external; /** * @notice Mints remaining token supply * @param stablecoin Stablecoin used for minting */ function mintRemainingSupply(IERC20Custom stablecoin) external; /** * @notice Sends accumulated DUSX to floor contract */ function sendToFloorDUSX() external; /** * @notice Verifies if a wallet is whitelisted * @param wallet Address to verify * @return bool Whitelist status */ function verifyWallet(address wallet) external view returns (bool); /** * @notice Calculates mint amount for given stablecoin input * @param stablecoin Stablecoin used for calculation * @param stableAmount Amount of stablecoin * @return uint256 Calculated mint amount */ function calcMintAmount( IERC20Custom stablecoin, uint256 stableAmount ) external view returns (uint256); /** * @notice Gets the current token reserve * @return uint256 Current token reserve */ function tokenReserve() external view returns (uint256); /** * @notice Gets the current mint ratio * @return uint256 Current mint ratio */ function getCurrentRatio() external view returns (uint256); /** * @notice Gets the current mint rate * @return uint256 Current mint rate */ function getCurrentRate() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IDynamicInterestRate} from "./IDynamicInterestRate.sol"; import {IFeesDistributor} from "./IFees.sol"; import {IFeesWithdrawer} from "./IFees.sol"; import {IFloor} from "./IFloor.sol"; import {ILender} from "./ILender.sol"; import {ILenderOwner} from "./ILenderOwner.sol"; import {ILiquidationHelper} from "./ILiquidationHelper.sol"; import {IMarketLens} from "./IMarketLens.sol"; import {IPSM} from "./IPSM.sol"; import {IRepayHelper} from "./IRepayHelper.sol"; import {IStakedDUSX} from "./IStakedDUSX.sol"; import {ISupplyHangingCalculator} from "./ISupplyHangingCalculator.sol"; /** * @title IMiscHelper * @dev Interface for miscellaneous helper functions across the protocol * @notice Provides comprehensive helper methods for: * 1. Protocol configuration and parameter management * 2. Floor token operations * 3. Staked DUSX token management * 4. PSM (Peg Stability Module) operations * 5. Lending operations including borrowing and repayment * 6. System-wide view functions * * This interface acts as a central utility hub for coordinating * various protocol components and simplifying complex operations */ interface IMiscHelper { /*////////////////////////////////////////////////////////////// CONFIGURATION FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Sets the supply hanging calculator contract * @param supplyHangingCalculator_ New calculator contract address * @dev Used for calculating supply adjustments */ function setSupplyHangingCalculator( ISupplyHangingCalculator supplyHangingCalculator_ ) external; /** * @notice Sets core protocol parameters and contract addresses * @param repayHelper_ Repayment helper contract * @param liquidationHelper_ Liquidation helper contract * @param dynamicInterestRate_ Interest rate calculator * @param feesDistributor_ Fee distribution contract * @param feesWithdrawer_ Fee withdrawal contract * @param lenderOwner_ Lender owner contract * @param marketLens_ Market data viewer contract * @dev Updates all main protocol component addresses */ function setParameters( IRepayHelper repayHelper_, ILiquidationHelper liquidationHelper_, IDynamicInterestRate dynamicInterestRate_, IFeesDistributor feesDistributor_, IFeesWithdrawer feesWithdrawer_, ILenderOwner lenderOwner_, IMarketLens marketLens_ ) external; /** * @notice Sets the list of active lender contracts * @param lenders_ Array of lender addresses * @dev Updates the protocol's lending markets */ function setLenders(ILender[] memory lenders_) external; /** * @notice Sets the list of PSM contracts * @param pegStabilityModules_ Array of PSM addresses * @dev Updates available stablecoin PSM modules */ function setPegStabilityModules( IPSM[] memory pegStabilityModules_ ) external; /*////////////////////////////////////////////////////////////// FLOOR TOKEN OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Deposits Floor tokens into the protocol * @param amount Amount of Floor tokens to deposit */ function depositFloor(uint256 amount) external; /** * @notice Refunds Floor tokens from the protocol * @param amount Amount of Floor tokens to refund */ function refundFloor(uint256 amount) external; /*////////////////////////////////////////////////////////////// STAKED DUSX OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Deposits DUSX tokens for staking * @param amount Amount of DUSX to stake */ function depositStakedDUSX(uint256 amount) external; /** * @notice Withdraws staked DUSX tokens * @param amount Amount of staked DUSX to withdraw */ function withdrawStakedDUSX(uint256 amount) external; /*////////////////////////////////////////////////////////////// PSM OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Swaps DUSX for stablecoin through PSM * @param psm PSM contract to use for swap * @param receiver Address to receive stablecoins * @param amountDUSX Amount of DUSX to swap */ function psmSwapDUSXForStable( IPSM psm, address receiver, uint256 amountDUSX ) external; /** * @notice Swaps stablecoin for DUSX through PSM * @param psm PSM contract to use for swap * @param receiver Address to receive DUSX * @param amountStable Amount of stablecoin to swap */ function psmSwapStableForDUSX( IPSM psm, address receiver, uint256 amountStable ) external; /*////////////////////////////////////////////////////////////// LENDING OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Withdraws borrowed tokens from vault * @param lender Lender contract to withdraw from * @param amount Amount to withdraw */ function lenderBorrowVaultWithdraw(ILender lender, uint256 amount) external; /** * @notice Executes a borrow operation * @param lender Lender contract to borrow from * @param amount Amount to borrow */ function lenderBorrow(ILender lender, uint256 amount) external; /** * @notice Repays borrowed tokens * @param lender Lender contract to repay to * @param payer Address paying the debt * @param to Address receiving any excess * @param skim Whether to skim tokens from contract * @param part Amount of borrow part to repay */ function lenderRepay( ILender lender, address payer, address to, bool skim, uint256 part ) external; /** * @notice Executes liquidation for multiple users * @param lender Lender contract to liquidate from * @param liquidator Address performing liquidation * @param users Array of addresses to liquidate * @param maxBorrowParts Maximum borrow parts to liquidate per user * @param to Address to receive liquidated assets */ function lenderLiquidate( ILender lender, address liquidator, address[] memory users, uint256[] memory maxBorrowParts, address to ) external; /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Returns current APR for staked DUSX * @return uint256 Annual percentage rate */ function aprStakedDUSX() external view returns (uint256); /** * @notice Returns repayment helper contract */ function repayHelper() external view returns (IRepayHelper); /** * @notice Returns liquidation helper contract */ function liquidationHelper() external view returns (ILiquidationHelper); /** * @notice Returns dynamic interest rate calculator */ function dynamicInterestRate() external view returns (IDynamicInterestRate); /** * @notice Returns floor token contract */ function floor() external view returns (IFloor); /** * @notice Returns fees distributor contract */ function feesDistributor() external view returns (IFeesDistributor); /** * @notice Returns fees withdrawer contract */ function feesWithdrawer() external view returns (IFeesWithdrawer); /** * @notice Returns lender contract at specified index * @param index Position in lenders array */ function lenders(uint256 index) external view returns (ILender); /** * @notice Returns total number of lender contracts */ function lendersLength() external view returns (uint256); /** * @notice Returns lender owner contract */ function lenderOwner() external view returns (ILenderOwner); /** * @notice Returns market lens contract */ function marketLens() external view returns (IMarketLens); /** * @notice Returns PSM contract at specified index * @param index Position in PSM array */ function pegStabilityModules(uint256 index) external view returns (IPSM); /** * @notice Returns total number of PSM contracts */ function pegStabilityModulesLength() external view returns (uint256); /** * @notice Returns staked DUSX token contract */ function stDUSX() external view returns (IStakedDUSX); /** * @notice Returns supply hanging calculator contract */ function supplyHangingCalculator() external view returns (ISupplyHangingCalculator); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title IOracle * @dev Interface for basic price feed operations * @notice Defines functionality for: * 1. Asset price retrieval * 2. Price precision handling */ interface IOracle { /*////////////////////////////////////////////////////////////// PRICE QUERIES //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves current asset price * @param asset Address of the asset to price * @return uint256 Current price in base units with precision * @dev Provides: * · Latest price data * · Standardized precision * · Asset valuation * * Note: Check implementation for specific precision details */ function getPrice(address asset) external view returns (uint256); } /** * @title ITwapOracle * @dev Interface for time-weighted average price calculations * @notice Defines functionality for: * 1. TWAP updates * 2. Time-weighted calculations * 3. Price smoothing */ interface ITwapOracle { /*////////////////////////////////////////////////////////////// TWAP OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Updates time-weighted average price * @param asset Address of the asset to update * @return uint256 New TWAP value in base units * @dev Calculates: * · Time-weighted price * · Cumulative values * · Price averages * * Features: * · Manipulation resistance * · Smoothing effect * · Historical tracking */ function updateTwap(address asset) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IERC20Custom} from "./IERC20Custom.sol"; /** * @title IPSM * @dev Interface for Peg Stability Module (PSM) operations * @notice Defines functionality for: * 1. Stablecoin/DUSX swaps * 2. Peg maintenance * 3. Supply tracking */ interface IPSM { /*////////////////////////////////////////////////////////////// SWAP OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Executes stablecoin to DUSX swap * @param msgSender Address initiating the swap * @param receiver Address receiving the DUSX * @param stableTokenAmount Amount of stablecoins to swap * @dev Handles: * · Stablecoin deposit * · DUSX minting * · Supply tracking */ function swapStableForDUSX( address msgSender, address receiver, uint256 stableTokenAmount ) external; /** * @notice Executes DUSX to stablecoin swap * @param msgSender Address initiating the swap * @param receiver Address receiving the stablecoins * @param stableTokenAmount Amount of stablecoins to receive * @dev Handles: * · DUSX burning * · Stablecoin release * · Supply adjustment */ function swapDUSXForStable( address msgSender, address receiver, uint256 stableTokenAmount ) external; /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves the stablecoin token contract * @return IERC20Custom Stablecoin token interface * @dev Used for: * · Token transfers * · Balance checks * · Allowance verification */ function stableToken() external view returns (IERC20Custom); /** * @notice Returns total DUSX tokens minted through PSM * @return uint256 Total minted amount in base units * @dev Tracks: * · Total supply impact * · PSM utilization * · Protocol growth metrics */ function dusxMinted() external view returns (uint256); /** * @notice Returns the maximum amount of DUSX that can be minted through PSM * @return uint256 Maximum mintable amount in base units * @dev Used for: * · Supply control * · Risk management * · Protocol safety */ function dusxMintCap() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IERC20Custom} from "./IERC20Custom.sol"; import {ILender} from "./ILender.sol"; import {IMiscHelper} from "./IMiscHelper.sol"; /** * @title IRepayHelper * @dev Interface for streamlined loan repayment operations and management * @notice Defines functionality for: * 1. Loan repayment processing * 2. Multi-loan management * 3. Helper contract integration * 4. Token interactions */ interface IRepayHelper { /*////////////////////////////////////////////////////////////// CONFIGURATION //////////////////////////////////////////////////////////////*/ /*////////////////////////////////////////////////////////////// REPAYMENT OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Processes partial loan repayment * @param lender Address of the lending contract * @param to Address whose loan is being repaid * @param amount Amount to repay in base units * @return part Share of the loan repaid * @dev Handles: * · Token transfers * · Loan accounting * · Share calculations * * Requirements: * · Amount > 0 * · Sufficient balance * · Valid addresses */ function repayAmount( ILender lender, address to, uint256 amount ) external returns (uint256 part); /** * @notice Processes complete loan repayment * @param lender Address of the lending contract * @param to Address whose loan is being repaid * @return amount Total amount repaid in base units * @dev Manages: * · Full debt calculation * · Complete repayment * · Account settlement * * Effects: * · Clears entire debt * · Updates balances * · Emits events */ function repayTotal( ILender lender, address to ) external returns (uint256 amount); /** * @notice Processes multiple complete loan repayments * @param lender Address of the lending contract * @param tos Array of addresses whose loans are being repaid * @return amount Total amount repaid across all loans * @dev Executes: * · Batch processing * · Multiple settlements * · Aggregate accounting * * Optimizations: * · Gas efficient * · Bulk processing * · Single transaction */ function repayTotalMultiple( ILender lender, address[] calldata tos ) external returns (uint256 amount); /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves DUSX token contract * @return IERC20Custom Interface of the DUSX token * @dev Used for: * · Token operations * · Balance checks * · Allowance verification */ function dusx() external view returns (IERC20Custom); /** * @notice Retrieves helper contract * @return IMiscHelper Interface of the helper contract * @dev Provides: * · Helper functionality * · Integration access * · Utility methods */ function helper() external view returns (IMiscHelper); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {IERC20Token} from "./IERC20Token.sol"; /** * @title IStableOwner Interface * @dev Interface for StableOwner contract that manages stable token supply * @notice Defines the external interface for stable token supply management */ interface IStableOwner { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ /// @notice Emitted when stable token contract is updated /// @param stable New stable token contract address event StableSet(IERC20Token indexed stable); /// @notice Emitted when new tokens are minted /// @param account Recipient of minted tokens /// @param amount Amount of tokens minted event TokensMinted(address indexed account, uint256 amount); /// @notice Emitted when tokens are burned /// @param account Account tokens were burned from /// @param amount Amount of tokens burned event TokensBurned(address indexed account, uint256 amount); /*////////////////////////////////////////////////////////////// FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Updates the stable token contract address /// @param stable_ New stable token contract address function setStable(IERC20Token stable_) external; /// @notice Creates new stable tokens /// @param account Address to receive minted tokens /// @param amount Number of tokens to mint function mint(address account, uint256 amount) external; /// @notice Destroys existing stable tokens /// @param account Address to burn tokens from /// @param amount Number of tokens to burn function burn(address account, uint256 amount) external; /// @notice The managed stable token contract /// @return The IERC20Token interface of the stable token function stable() external view returns (IERC20Token); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title IStakedDUSX * @dev Interface for staked DUSX token operations and reward distribution * @notice Defines functionality for: * 1. DUSX token staking * 2. Reward distribution * 3. Position management */ interface IStakedDUSX { /*////////////////////////////////////////////////////////////// REWARD DISTRIBUTION //////////////////////////////////////////////////////////////*/ /** * @notice Distributes protocol fees as staking rewards * @param amount Amount of fees to distribute in base units * @dev Handles: * · Pro-rata distribution * · Reward accounting * · Distribution events * * Rewards are: * · Automatically calculated * · Immediately available * · Proportional to stake */ function distributeFees(uint256 amount) external; /** * @notice Claims pending fee rewards for the caller * @return claimedAmount Amount of fees claimed * @dev Allows users to manually claim their accumulated fees */ function claimFees() external returns (uint256 claimedAmount); /*////////////////////////////////////////////////////////////// STAKING OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Processes DUSX token deposits for staking * @param from Address providing the tokens * @param to Address receiving the staked position * @param amount Quantity of tokens to stake in base units * @dev Manages: * · Token transfers * · Position creation * · Reward calculations * * Supports: * · Direct deposits * · Delegated deposits * · Position tracking */ function deposit(address from, address to, uint256 amount) external; /** * @notice Initiates a withdrawal from staked DUSX * @param amount Amount of tokens to withdraw */ function beginWithdrawal(uint256 amount) external; /** * @notice Processes withdrawal of staked DUSX tokens * @param account Address withdrawing tokens * @dev Handles: * · Position updates * · Reward claims * · Token transfers * * Ensures: * · Sufficient balance * · Reward distribution * · Clean exit */ function withdraw(address account) external; /** * @notice Views pending unclaimed fees for an account * @param account Address to check for pending fees * @return pendingAmount Amount of pending fees available to claim * @dev Calculates based on the fee accumulator and account's last claimed value */ function pendingFees( address account ) external view returns (uint256 pendingAmount); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title ISupplyHangingCalculator * @dev Interface for calculating and managing token supply adjustments * @notice Defines functionality for: * 1. Supply hanging calculations * 2. Safety margin management * 3. Risk-adjusted metrics */ interface ISupplyHangingCalculator { /*////////////////////////////////////////////////////////////// SAFETY PARAMETERS //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves current safety margin for supply calculations * @return uint256 Safety margin percentage scaled by 1e18 * @dev Used for: * · Risk adjustment * · Supply buffer * · Protocol protection */ function safetyMargin() external view returns (uint256); /*////////////////////////////////////////////////////////////// SUPPLY HANGING CALCULATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Calculates current supply hanging with safety margins * @return uint256 Risk-adjusted supply hanging in base units * @dev Includes: * · Safety margin application * · Risk adjustments * · Protocol constraints * * Used for: * · Safe supply management * · Conservative adjustments * · Risk-aware operations */ function getSupplyHanging() external view returns (uint256); /** * @notice Calculates raw supply hanging without safety margins * @return uint256 Unadjusted supply hanging in base units * @dev Provides: * · Raw calculations * · No safety buffers * · Maximum theoretical values * * Used for: * · Analysis purposes * · Maximum bounds * · Stress testing */ function getSupplyHangingUnsafe() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; import {Rebase} from "../library/AuxRebase.sol"; import {IERC20Custom} from "./IERC20Custom.sol"; /** * @title IVault * @dev Interface for advanced vault operations with elastic share system * @notice Defines functionality for: * 1. Token custody and management * 2. Share-based accounting * 3. Elastic supply mechanics * 4. Amount/share conversions */ interface IVault { /*////////////////////////////////////////////////////////////// DEPOSIT OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Processes token deposits into vault * @param token Token contract to deposit * @param from Source of tokens * @param to Recipient of shares * @param amount Token amount (in base units, 0 for share-based) * @param share Share amount (0 for amount-based) * @return amountIn Actual tokens deposited * @return shareIn Actual shares minted * @dev Handles: * · Token transfers * · Share minting * · Balance updates * * Requirements: * · Valid token contract * · Authorized caller * · Sufficient balance * · Either amount or share > 0 * * Note: Only one of amount/share should be non-zero */ function deposit( IERC20Custom token, address from, address to, uint256 amount, uint256 share ) external returns (uint256 amountIn, uint256 shareIn); /*////////////////////////////////////////////////////////////// WITHDRAWAL OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Processes token withdrawals from vault * @param token Token contract to withdraw * @param from Source of shares * @param to Recipient of tokens * @param amount Token amount (in base units, 0 for share-based) * @param share Share amount (0 for amount-based) * @return amountOut Actual tokens withdrawn * @return shareOut Actual shares burned * @dev Manages: * · Share burning * · Token transfers * · Balance updates * * Requirements: * · Valid token contract * · Sufficient shares * · Either amount or share > 0 * · Authorized withdrawal * * Security: * · Validates balances * · Checks permissions * · Updates state atomically */ function withdraw( IERC20Custom token, address from, address to, uint256 amount, uint256 share ) external returns (uint256 amountOut, uint256 shareOut); /*////////////////////////////////////////////////////////////// SHARE TRANSFERS //////////////////////////////////////////////////////////////*/ /** * @notice Transfers vault shares between accounts * @param token Associated token contract * @param from Source of shares * @param to Recipient of shares * @param share Amount of shares to transfer * @dev Executes: * · Direct share movement * · Balance updates * · Event emission * * Requirements: * · Sufficient share balance * · Valid addresses * · Share amount > 0 * * Note: Bypasses amount calculations for efficiency */ function transfer( IERC20Custom token, address from, address to, uint256 share ) external; /*////////////////////////////////////////////////////////////// BALANCE QUERIES //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves account's vault share balance * @param token Token contract to query * @param account Address to check * @return uint256 Share balance * @dev Provides: * · Raw share balance * · Without conversion * · Current state * * Use toAmount() to convert to token amount */ function balanceOf( IERC20Custom token, address account ) external view returns (uint256); /*////////////////////////////////////////////////////////////// CONVERSION OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Converts token amount to vault shares * @param token Token contract for conversion * @param amount Amount of tokens to convert * @param roundUp Whether to round up result * @return share Equivalent share amount * @dev Calculates: * · Share equivalent * · Based on totals * · Handles precision * * Rounding: * true = ceiling (≥) * false = floor (≤) */ function toShare( IERC20Custom token, uint256 amount, bool roundUp ) external view returns (uint256 share); /** * @notice Converts vault shares to token amount * @param token Token contract for conversion * @param share Amount of shares to convert * @param roundUp Whether to round up result * @return amount Equivalent token amount * @dev Calculates: * · Token equivalent * · Based on totals * · Handles precision * * Rounding: * true = ceiling (≥) * false = floor (≤) */ function toAmount( IERC20Custom token, uint256 share, bool roundUp ) external view returns (uint256 amount); /** * @notice Gets the list of active controllers * @return Array of controller addresses */ function getControllers() external view returns (address[] memory); /*////////////////////////////////////////////////////////////// VAULT TOTALS //////////////////////////////////////////////////////////////*/ /** * @notice Retrieves vault's total supply tracking * @param token Token contract to query * @return vaultTotals Rebase struct containing: * · elastic: Total token amount * · base: Total shares * @dev Provides: * · Current vault state * · Supply tracking * · Conversion basis * * Used for: * · Share calculations * · Amount conversions * · State validation */ function totals( IERC20Custom token ) external view returns (Rebase memory vaultTotals); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title IVoteEscrowedSTTX * @dev Interface for vote-escrowed STTX (veSTTX) token operations * @notice Defines functionality for: * 1. Token withdrawal management * 2. Escrow position handling * 3. Voting power release */ interface IVoteEscrowedSTTX { /*////////////////////////////////////////////////////////////// WITHDRAWAL OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Processes withdrawal of escrowed STTX tokens * @dev Handles: * · Lock period verification * · Position liquidation * · Token transfers * * Requirements: * · Lock period expired * · Active position exists * · Caller is position owner * * Effects: * · Releases locked tokens * · Removes voting power * · Clears escrow position */ function withdraw() external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.24 <0.9.0; /** * @title Rebase Library * @dev Library for handling elastic supply token calculations and adjustments * @notice This library provides mathematical operations for elastic/base token conversions * and supply adjustments. It handles two key concepts: * * 1. Elastic Supply: The actual total supply that can expand or contract * 2. Base Supply: The underlying base amount that remains constant */ /*////////////////////////////////////////////////////////////// TYPES //////////////////////////////////////////////////////////////*/ /** * @dev Core data structure for elastic supply tracking * @param elastic Current elastic (rebased) supply * @param base Current base (non-rebased) supply */ struct Rebase { uint256 elastic; uint256 base; } /** * @title AuxRebase * @dev Auxiliary functions for elastic supply calculations * @notice Provides safe mathematical operations for elastic/base conversions * with optional rounding control */ library AuxRebase { /*////////////////////////////////////////////////////////////// ELASTIC SUPPLY OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Increases the elastic supply * @param total Current total supply state * @param elastic Amount to add to elastic supply * @return newElastic Updated elastic supply after addition */ function addElastic( Rebase storage total, uint256 elastic ) internal returns (uint256 newElastic) { newElastic = total.elastic += elastic; } /** * @notice Decreases the elastic supply * @param total Current total supply state * @param elastic Amount to subtract from elastic supply * @return newElastic Updated elastic supply after subtraction */ function subElastic( Rebase storage total, uint256 elastic ) internal returns (uint256 newElastic) { newElastic = total.elastic -= elastic; } /*////////////////////////////////////////////////////////////// CONVERSION OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Converts an elastic amount to its base amount * @param total Current total supply state * @param elastic Amount of elastic tokens to convert * @param roundUp If true, rounds up the result * @return base Equivalent amount in base units * @dev * · If elastic supply is 0, returns elastic amount as base * · Handles potential precision loss during conversion * · Rounding can cause slight variations in converted amounts * · Recommended for scenarios requiring precise supply tracking * * Rounding Behavior: * · roundUp = false: Always rounds down (truncates) * · roundUp = true: Rounds up if there's a fractional remainder * * Edge Cases: * · total.elastic == 0: Returns input elastic as base * · Potential for minimal precision differences */ function toBase( Rebase memory total, uint256 elastic, bool roundUp ) internal pure returns (uint256 base) { if (total.elastic == 0) { base = elastic; } else { base = (elastic * total.base) / total.elastic; if (roundUp && (base * total.elastic) / total.base < elastic) { base++; } } } /** * @notice Converts a base amount to its elastic amount * @param total Current total supply state * @param base Amount of base tokens to convert * @param roundUp If true, rounds up the result * @return elastic Equivalent amount in elastic units * @dev * · If base supply is 0, returns base amount as elastic * · Handles potential precision loss during conversion * · Rounding can cause slight variations in converted amounts * · Recommended for scenarios requiring precise supply tracking * * Rounding Behavior: * · roundUp = false: Always rounds down (truncates) * · roundUp = true: Rounds up if there's a fractional remainder * * Edge Cases: * · total.base == 0: Returns input base as elastic * · Potential for minimal precision differences */ function toElastic( Rebase memory total, uint256 base, bool roundUp ) internal pure returns (uint256 elastic) { if (total.base == 0) { elastic = base; } else { elastic = (base * total.elastic) / total.base; if (roundUp && (elastic * total.base) / total.elastic < base) { elastic++; } } } /*////////////////////////////////////////////////////////////// COMBINED OPERATIONS //////////////////////////////////////////////////////////////*/ /** * @notice Adds elastic tokens and calculates corresponding base amount * @param total Current total supply state * @param elastic Amount of elastic tokens to add * @param roundUp If true, rounds up base conversion * @return (Rebase, uint256) Updated total supply and calculated base amount */ function add( Rebase memory total, uint256 elastic, bool roundUp ) internal pure returns (Rebase memory, uint256 base) { base = toBase(total, elastic, roundUp); total.elastic += elastic; total.base += base; return (total, base); } /** * @notice Subtracts base tokens and calculates corresponding elastic amount * @param total Current total supply state * @param base Amount of base tokens to subtract * @param roundUp If true, rounds up elastic conversion * @return (Rebase, uint256) Updated total supply and calculated elastic amount */ function sub( Rebase memory total, uint256 base, bool roundUp ) internal pure returns (Rebase memory, uint256 elastic) { elastic = toElastic(total, base, roundUp); total.elastic -= elastic; total.base -= base; return (total, elastic); } /** * @notice Adds specific amounts to both elastic and base supplies * @param total Current total supply state * @param elastic Amount of elastic tokens to add * @param base Amount of base tokens to add * @return Rebase Updated total supply after addition */ function add( Rebase memory total, uint256 elastic, uint256 base ) internal pure returns (Rebase memory) { total.elastic += elastic; total.base += base; return total; } /** * @notice Subtracts specific amounts from both elastic and base supplies * @param total Current total supply state * @param elastic Amount of elastic tokens to subtract * @param base Amount of base tokens to subtract * @return Rebase Updated total supply after subtraction */ function sub( Rebase memory total, uint256 elastic, uint256 base ) internal pure returns (Rebase memory) { total.elastic -= elastic; total.base -= base; return total; } }
{ "viaIR": true, "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IBaseContracts","name":"baseContracts_","type":"address"},{"internalType":"contract IERC20Custom","name":"collateral_","type":"address"},{"internalType":"uint256","name":"collateralRatio_","type":"uint256"},{"internalType":"uint256","name":"liquidationMultiplier_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllSolvent","type":"error"},{"inputs":[],"name":"BorrowLimitExceeded","type":"error"},{"inputs":[],"name":"ExchangeRateNotUpdated","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"InvalidOwner","type":"error"},{"inputs":[],"name":"InvalidParameter","type":"error"},{"inputs":[],"name":"InvalidSkim","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"UnauthorizedAccount","type":"error"},{"inputs":[],"name":"UserInsolvent","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"accruedAmount","type":"uint256"}],"name":"Accrued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"perAddressPart","type":"uint256"}],"name":"BorrowLimitChanged","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":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"part","type":"uint256"}],"name":"Borrowed","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":"share","type":"uint256"}],"name":"CollateralAdded","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":"share","type":"uint256"}],"name":"CollateralRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rate","type":"uint256"}],"name":"ExchangeRateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feeTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"feesEarnedFraction","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldInterestRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newInterestRate","type":"uint256"}],"name":"InterestRateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralShare","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowPart","type":"uint256"}],"name":"LiquidationExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"part","type":"uint256"}],"name":"Repaid","type":"event"},{"inputs":[],"name":"HUNDREDK_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANTISSA_ONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accrueInfo","outputs":[{"internalType":"uint256","name":"lastAccrued","type":"uint256"},{"internalType":"uint256","name":"feesEarned","type":"uint256"},{"internalType":"uint256","name":"interestPerSecond","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"skim","type":"bool"},{"internalType":"uint256","name":"share","type":"uint256"}],"name":"addCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrow","outputs":[{"internalType":"uint256","name":"part","type":"uint256"},{"internalType":"uint256","name":"share","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrowLimit","outputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"borrowPartPerAddress","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrowVaultWithdraw","outputs":[{"internalType":"uint256","name":"part","type":"uint256"},{"internalType":"uint256","name":"share","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newBorrowLimit","type":"uint256"},{"internalType":"uint256","name":"borrowPartPerAddress","type":"uint256"}],"name":"changeBorrowLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newInterestRate","type":"uint256"}],"name":"changeInterestRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract IERC20Custom","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralPrecision","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dusx","outputs":[{"internalType":"contract IERC20Token","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dusxProvider","outputs":[{"internalType":"contract IDUSXProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesWithdrawer","outputs":[{"internalType":"contract IFeesWithdrawer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"helper","outputs":[{"internalType":"contract IMiscHelper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isSolvent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidator","type":"address"},{"internalType":"address[]","name":"users","type":"address[]"},{"internalType":"uint256[]","name":"maxBorrowParts","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidationMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"share","type":"uint256"}],"name":"removeCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"removeCollateralVaultWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"payer","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"skim","type":"bool"},{"internalType":"uint256","name":"part","type":"uint256"}],"name":"repay","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalBorrow","outputs":[{"internalType":"uint256","name":"elastic","type":"uint256"},{"internalType":"uint256","name":"base","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCollateralShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateExchangeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBorrowPart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userCollateralShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"vaultDepositAddCollateral","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToProvide","type":"uint256"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610160604052346200020657620000236200001962000384565b9291909162000aaf565b6200002d6200020c565b6149b662001abd82396080518181816105e10152818161234801526139d0015260a05181818161055901528181611c1d01526140fa015260c051818181610ff30152611b26015260e0518181816110fb015281816115cc015281816116b00152818161171d01528181612202015281816127770152818161295601528181612fbd01528181613068015281816137510152818161392b01526147d6015261010051818181610df001528181611ba301528181611cba0152818161264c015281816126d801528181612c4d01528181612ca001528181612d92015281816132c50152818161335301528181613fd101528181614024015281816141990152614227015261012051818181610bba015261371f0152610140518181816112e30152818161159e0152818161167f01528181611b7501528181611c8e015281816121d30152818161261c015281816126ab0152818161274a0152818161298a01528181612c2101528181612c7101528181612d5f01528181612f8d01528181613037015281816132970152818161332701528181613380015281816133ff015281816138f501528181613ab001528181613ba201528181613fa501528181613ff50152818161416b015281816141fc01526147a901526149b690f35b62000212565b60405190565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b90620002439062000217565b810190811060018060401b038211176200025c57604052565b62000221565b9062000279620002716200020c565b928362000237565b565b600080fd5b60018060a01b031690565b620002969062000280565b90565b620002a4906200028b565b90565b620002b28162000299565b03620002ba57565b600080fd5b90505190620002ce82620002a7565b565b620002db906200028b565b90565b620002e981620002d0565b03620002f157565b600080fd5b905051906200030582620002de565b565b90565b620003158162000307565b036200031d57565b600080fd5b9050519062000331826200030a565b565b6080818303126200037e576200034d8260008301620002bf565b926200037b620003618460208501620002f6565b9362000371816040860162000322565b9360600162000322565b90565b6200027b565b620003a762006473803803806200039b8162000262565b92833981019062000333565b90919293565b90565b620003c9620003c3620003cf9262000280565b620003ad565b62000280565b90565b620003dd90620003b0565b90565b620003eb90620003d2565b90565b620003f990620003d2565b90565b60e01b90565b6200040d906200028b565b90565b6200041b8162000402565b036200042357565b600080fd5b90505190620004378262000410565b565b906020828203126200045657620004539160000162000428565b90565b6200027b565b60000190565b6200046c6200020c565b3d6000823e3d90fd5b62000480906200028b565b90565b6200048e8162000475565b036200049657565b600080fd5b90505190620004aa8262000483565b565b90602082820312620004c957620004c6916000016200049b565b90565b6200027b565b620004da906200028b565b90565b620004e881620004cf565b03620004f057565b600080fd5b905051906200050482620004dd565b565b9060208282031262000523576200052091600001620004f5565b90565b6200027b565b62000534906200028b565b90565b620005428162000529565b036200054a57565b600080fd5b905051906200055e8262000537565b565b906020828203126200057d576200057a916000016200054f565b90565b6200027b565b6200058e906200028b565b90565b6200059c8162000583565b03620005a457565b600080fd5b90505190620005b88262000591565b565b90602082820312620005d757620005d491600001620005a9565b90565b6200027b565b60001b90565b90620005f660018060a01b0391620005dd565b9181191691161790565b6200060b90620003b0565b90565b620006199062000600565b90565b90565b90620006396200063362000641926200060e565b6200061c565b8254620005e3565b9055565b62000650906200028b565b90565b6200065e8162000645565b036200066657565b600080fd5b905051906200067a8262000653565b565b90602082820312620006995762000696916000016200066b565b90565b6200027b565b620006ab905162000402565b90565b620006b990620003d2565b90565b620006c8905162000475565b90565b620006d690620003d2565b90565b620006e59051620004cf565b90565b620006f390620003d2565b90565b62000702905162000529565b90565b6200071090620003d2565b90565b60001c90565b60018060a01b031690565b62000733620007399162000713565b62000719565b90565b62000748905462000724565b90565b6200075690620003d2565b90565b6200076490620003d2565b90565b600090565b62000777906200028b565b90565b62000785816200076c565b036200078d57565b600080fd5b90505190620007a1826200077a565b565b90602082820312620007c057620007bd9160000162000792565b90565b6200027b565b620007d190620003d2565b90565b620007df906200028b565b90565b620007ed81620007d4565b03620007f557565b600080fd5b905051906200080982620007e2565b565b9060208282031262000828576200082591600001620007fa565b90565b6200027b565b6200083990620003d2565b90565b60ff1690565b6200084d816200083c565b036200085557565b600080fd5b90505190620008698262000842565b565b90602082820312620008885762000885916000016200085a565b90565b6200027b565b90565b620008aa620008a4620008b0926200088e565b620003ad565b6200083c565b90565b634e487b7160e01b600052601160045260246000fd5b620008d4906200083c565b604d8111620008e357600a0a90565b620008b3565b620008f490620003d2565b90565b90565b90620009146200090e6200091c92620008e9565b620008f7565b8254620005e3565b9055565b906200092f60001991620005dd565b9181191691161790565b620009526200094c620009589262000307565b620003ad565b62000307565b90565b90565b906200097862000972620009809262000939565b6200095b565b825462000920565b9055565b90565b620009a06200099a620009a69262000984565b620003ad565b62000307565b90565b620009b5604062000262565b90565b90565b620009d4620009ce620009da92620009b8565b620003ad565b62000307565b90565b90620009e99062000307565b9052565b620009f9905162000307565b90565b9062000a306020600162000a379462000a276000820162000a2060008801620009ed565b906200095e565b019201620009ed565b906200095e565b565b9062000a4591620009fc565b565b62000a539051620007d4565b90565b62000a629051620002d0565b90565b9060208282031262000a825762000a7f9160000162000322565b90565b6200027b565b62000a93906200028b565b9052565b919062000aad9060006020850194019062000a88565b565b92919262000abc620013b9565b62000ad162000acb82620003e0565b62001421565b62000ae662000ae083620003ee565b62001421565b8160e05262000b14602062000afb83620003e0565b63fbfa77cf9062000b0b6200020c565b938492620003fc565b8252818062000b26600482016200045c565b03915afa9081156200137f576000916200134a575b506101405262000b6a602062000b5183620003e0565b6396df10c09062000b616200020c565b938492620003fc565b8252818062000b7c600482016200045c565b03915afa90811562001344576000916200130f575b506101005262000bc0602062000ba783620003e0565b633d5064199062000bb76200020c565b938492620003fc565b8252818062000bd2600482016200045c565b03915afa9081156200130957600091620012d4575b5060a05262000c15602062000bfc83620003e0565b63cbfd73d59062000c0c6200020c565b938492620003fc565b8252818062000c27600482016200045c565b03915afa908115620012ce5760009162001299575b5060c05262000c6a602062000c5183620003e0565b6363b0e66a9062000c616200020c565b938492620003fc565b8252818062000c7c600482016200045c565b03915afa8015620012935762000c9e916000916200125e575b50600d6200061f565b62000cc8602062000caf83620003e0565b63cc5005969062000cbf6200020c565b938492620003fc565b8252818062000cda600482016200045c565b03915afa908115620012585760009162001223575b5062000d1162000d0b62000d056101406200069f565b620006ae565b62001421565b62000d3262000d2c62000d26610100620006bc565b620006cb565b62001421565b62000d5262000d4c62000d4660a0620006d9565b620006e8565b62001421565b62000d7262000d6c62000d6660c0620006f6565b62000705565b62001421565b62000d9262000d8c62000d86600d6200073c565b6200074b565b62001421565b62000da762000da18262000759565b62001421565b62000db162000767565b5062000dbd83620003ee565b62000de7602062000dce85620003e0565b635c2c7cc69062000dde6200020c565b938492620003fc565b8252818062000df9600482016200045c565b03915afa80156200121d5762000e2262000e289162000e2f93600091620011e8575b50620007c6565b6200028b565b916200028b565b146000146200114157602062000e4962000e6293620003e0565b63ba826c369062000e596200020c565b948592620003fc565b8252818062000e74600482016200045c565b03915afa9283156200113b5762000ec562000ebf62000ecb9362000ee49660209660009162001107575b505b62000eb562000eaf826200082e565b62001421565b6101205262000759565b620014f2565b620003ee565b63313ce5679062000edb6200020c565b938492620003fc565b8252818062000ef6600482016200045c565b03915afa9081156200110157600091620010cc575b508062000f2462000f1d601262000891565b916200083c565b11620010a55762000f739262000f3e62000f6b92620008c9565b60805262000f6362000f5b62000f5560c0620006f6565b62000705565b600e620008fa565b60096200095e565b600b6200095e565b62000f9062000f866312e337ef62000987565b600280016200095e565b62000fdb600062000fd362000fc9600062000fc362000fb962000fb2620009a9565b95620009bb565b60008601620009dd565b620009bb565b60208301620009dd565b600562000a39565b6200103c602062000ff862000ff261012062000a47565b6200082e565b6341976e099062001030620010186200101260e062000a56565b620003ee565b92620010236200020c565b95869485938493620003fc565b83526004830162000a97565b03915afa80156200109f576200105e916000916200106a575b50600a6200095e565b62001068620017ef565b565b62001090915060203d811162001097575b62001087818362000237565b81019062000a65565b3862001055565b503d6200107b565b62000462565b620010af6200020c565b630309cb8760e51b815280620010c8600482016200045c565b0390fd5b620010f2915060203d8111620010f9575b620010e9818362000237565b8101906200086b565b3862000f0b565b503d620010dd565b62000462565b6200112c9150873d811162001133575b62001123818362000237565b8101906200080b565b3862000e9e565b503d62001117565b62000462565b6020620011526200116b93620003e0565b634f7b02ee90620011626200020c565b948592620003fc565b825281806200117d600482016200045c565b03915afa928315620011e25762000ec562000ebf62000ecb9362000ee496602096600091620011ae575b5062000ea0565b620011d39150873d8111620011da575b620011ca818362000237565b8101906200080b565b38620011a7565b503d620011be565b62000462565b6200120e915060203d811162001215575b62001205818362000237565b810190620007a3565b3862000e1b565b503d620011f9565b62000462565b62001249915060203d811162001250575b62001240818362000237565b8101906200067c565b3862000cef565b503d62001234565b62000462565b62001284915060203d81116200128b575b6200127b818362000237565b810190620005ba565b3862000c95565b503d6200126f565b62000462565b620012bf915060203d8111620012c6575b620012b6818362000237565b81019062000560565b3862000c3c565b503d620012aa565b62000462565b620012fa915060203d811162001301575b620012f1818362000237565b81019062000506565b3862000be7565b503d620012e5565b62000462565b62001335915060203d81116200133c575b6200132c818362000237565b810190620004ac565b3862000b91565b503d62001320565b62000462565b62001370915060203d811162001377575b62001367818362000237565b81019062000439565b3862000b3b565b503d6200135b565b62000462565b90565b620013a16200139b620013a79262001385565b620003ad565b62000307565b90565b620013b6600162001388565b90565b620013c3620013db565b620013d9620013d1620013aa565b60016200095e565b565b620013ef620013e962001990565b620019d1565b565b6200140a620014046200141092620009b8565b620003ad565b62000280565b90565b6200141e90620013f1565b90565b620014426200143b62001435600062001413565b6200028b565b916200028b565b146200144a57565b620014546200020c565b63d92e233d60e01b8152806200146d600482016200045c565b0390fd5b62001486906200148062001a3e565b62001488565b565b80620014aa620014a36200149d600062001413565b6200028b565b916200028b565b14620014bd57620014bb90620019d1565b565b620014ee620014cd600062001413565b620014d76200020c565b91829163b20f76e360e01b83526004830162000a97565b0390fd5b620014fd9062001471565b565b90565b62001511620015179162000713565b620014ff565b90565b62001526905462001502565b90565b62001535606062000262565b90565b90620015976200158d60026200154d62001529565b946200156a62001560600083016200151a565b60008801620009dd565b620015866200157c600183016200151a565b60208801620009dd565b016200151a565b60408401620009dd565b565b620015a49062001538565b90565b620015b9620015c09193929362000307565b9262000307565b8203918211620015cc57565b620008b3565b620015de604062000262565b90565b90620016246200161a6001620015f6620015d2565b946200161362001609600083016200151a565b60008801620009dd565b016200151a565b60208401620009dd565b565b6200163190620015e1565b90565b9062001685604060026200168c946200165f600082016200165860008801620009ed565b906200095e565b6200167c600182016200167560208801620009ed565b906200095e565b019201620009ed565b906200095e565b565b906200169a9162001634565b565b620016ae620016b59193929362000307565b9262000307565b91620016c383820262000307565b928184041490151715620016d357565b620008b3565b90565b620016f5620016ef620016fb92620016d9565b620003ad565b62000307565b90565b62001711670de0b6b3a7640000620016dc565b90565b634e487b7160e01b600052601260045260246000fd5b62001739620017409162000307565b9162000307565b9081156200174c570490565b62001714565b620017646200176b9193929362000307565b9262000307565b82018092116200177757565b620008b3565b90620017b160206001620017b894620017a860008201620017a160008801620009ed565b906200095e565b019201620009ed565b906200095e565b565b90620017c6916200177d565b565b620017d39062000307565b9052565b9190620017ed90600060208501940190620017c8565b565b620017fb600262001599565b62001815426200180e60008401620009ed565b90620015a7565b90816200182e620018276000620009bb565b9162000307565b14620019875762001840600762001626565b916200184f60208401620009ed565b620018666200185f6000620009bb565b9162000307565b14620019675790620018eb620018bc620018ab6200192894620018a56200189060008901620009ed565b6200189e60408801620009ed565b906200169c565b6200169c565b620018b5620016fe565b906200172a565b93620018e385620018dc6000840191620018d683620009ed565b62001752565b90620009dd565b6007620017ba565b62001911836200190a60208401916200190483620009ed565b62001752565b90620009dd565b620019204260008301620009dd565b60026200168e565b620019627ff3486c8be7415104f077b000d812e60c482b6824642b7673b3f73d6faeca29a691620019586200020c565b91829182620017d7565b0390a1565b506200198591506200197d4260008301620009dd565b60026200168e565b565b5050565b600090565b6200199a6200198b565b503390565b60018060a01b031690565b620019b9620019bf9162000713565b6200199f565b90565b620019ce9054620019aa565b90565b620019dd6000620019c2565b620019ea826000620008fa565b9062001a2262001a1b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e093620008e9565b91620008e9565b9162001a2d6200020c565b8062001a39816200045c565b0390a3565b62001a4862001aa2565b62001a6762001a6062001a5a62001990565b6200028b565b916200028b565b0362001a6f57565b62001a9e62001a7d62001990565b62001a876200020c565b9182916332b2baa360e01b83526004830162000a97565b0390fd5b62001aac6200198b565b5062001ab96000620019c2565b9056fe60806040526004361015610013575b611369565b61001e60003561026d565b8063017e7e581461026857806302ce728f146102635780631c9e379b1461025e57806338b51ce1146102595780633ba0b9a9146102545780633d5064191461024f578063430aea2e1461024a578063473e3ce7146102455780634886cf321461024057806348e4163e1461023b5780634b8a3529146102365780634c343f0014610231578063529898f21461022c5780635e318e071461022757806363b0e66a14610222578063715018a61461021d5780637ce69001146102185780637dc0d1d0146102135780638285ef401461020e578063860ffea114610209578063876467f8146102045780638a1bdb54146101ff5780638da5cb5b146101fa57806396df10c0146101f55780639b821418146101f0578063ad3b55ce146101eb578063b27c0e74146101e6578063b4eae1cb146101e1578063cbfd73d5146101dc578063cd0211eb146101d7578063d8dfeb45146101d2578063e551d11d146101cd578063f23c0f40146101c8578063f2fde38b146101c3578063f5d93f52146101be578063f8ba4cff146101b95763fbfa77cf0361000e57611334565b6112ae565b61127b565b611248565b611213565b61119f565b61114c565b6110c0565b611044565b610fbc565b610f74565b610ee2565b610e76565b610e41565b610db9565b610d82565b610d4e565b610d1a565b610c85565b610c0b565b610b81565b610940565b61090b565b610868565b610833565b6107ef565b61078a565b610703565b6106c0565b610648565b610603565b6105aa565b610522565b6104dd565b610480565b61034d565b610312565b60e01c90565b60405190565b600080fd5b600080fd5b600091031261028e57565b61027e565b1c90565b60018060a01b031690565b6102b29060086102b79302610293565b610297565b90565b906102c591546102a2565b90565b6102d5600e6000906102ba565b90565b60018060a01b031690565b6102ec906102d8565b90565b6102f8906102e3565b9052565b9190610310906000602085019401906102ef565b565b3461034257610322366004610283565b61033e61032d6102c8565b610335610273565b918291826102fc565b0390f35b610279565b60000190565b3461037b5761035d366004610283565b610365611393565b61036d610273565b8061037781610347565b0390f35b610279565b600080fd5b61038e816102e3565b0361039557565b600080fd5b905035906103a782610385565b565b906020828203126103c3576103c09160000161039a565b90565b61027e565b90565b6103df6103da6103e4926102d8565b6103c8565b6102d8565b90565b6103f0906103cb565b90565b6103fc906103e7565b90565b90610409906103f3565b600052602052604060002090565b90565b61042a90600861042f9302610293565b610417565b90565b9061043d915461041a565b90565b610457906104526010916000926103ff565b610432565b90565b90565b6104669061045a565b9052565b919061047e9060006020850194019061045d565b565b346104b0576104ac61049b6104963660046103a9565b610440565b6104a3610273565b9182918261046a565b0390f35b610279565b151590565b6104c3906104b5565b9052565b91906104db906000602085019401906104ba565b565b3461050d576105096104f86104f33660046103a9565b6113a2565b610500610273565b918291826104c7565b0390f35b610279565b61051f600a600090610432565b90565b3461055257610532366004610283565b61054e61053d610512565b610545610273565b9182918261046a565b0390f35b610279565b7f000000000000000000000000000000000000000000000000000000000000000090565b610584906103e7565b90565b6105909061057b565b9052565b91906105a890600060208501940190610587565b565b346105da576105ba366004610283565b6105d66105c5610557565b6105cd610273565b91829182610594565b0390f35b610279565b7f000000000000000000000000000000000000000000000000000000000000000090565b3461063357610613366004610283565b61062f61061e6105df565b610626610273565b9182918261046a565b0390f35b610279565b610645600c600090610432565b90565b3461067857610658366004610283565b610674610663610638565b61066b610273565b9182918261046a565b0390f35b610279565b6106868161045a565b0361068d57565b600080fd5b9050359061069f8261067d565b565b906020828203126106bb576106b891600001610692565b90565b61027e565b6106d36106ce3660046106a1565b61180b565b6106db610273565b806106e581610347565b0390f35b610700906106fb600f916000926103ff565b610432565b90565b346107335761072f61071e6107193660046103a9565b6106e9565b610726610273565b9182918261046a565b0390f35b610279565b9190604083820312610761578061075561075e926000860161039a565b93602001610692565b90565b61027e565b9160206107889294936107816040820196600083019061045d565b019061045d565b565b346107bc576107a361079d366004610738565b90611938565b906107b86107af610273565b92839283610766565b0390f35b610279565b91906040838203126107ea57806107de6107e79260008601610692565b93602001610692565b90565b61027e565b3461081e576108086108023660046107c1565b90611a3d565b610810610273565b8061081a81610347565b0390f35b610279565b610830600b600090610432565b90565b3461086357610843366004610283565b61085f61084e610823565b610856610273565b9182918261046a565b0390f35b610279565b346108965761088061087b3660046106a1565b611e4d565b610888610273565b8061089281610347565b0390f35b610279565b60018060a01b031690565b6108b69060086108bb9302610293565b61089b565b90565b906108c991546108a6565b90565b6108d9600d6000906108be565b90565b6108e5906103e7565b90565b6108f1906108dc565b9052565b9190610909906000602085019401906108e8565b565b3461093b5761091b366004610283565b6109376109266108cc565b61092e610273565b918291826108f5565b0390f35b610279565b3461096e57610950366004610283565b610958611ea6565b610960610273565b8061096a81610347565b0390f35b610279565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b906109a290610978565b810190811067ffffffffffffffff8211176109bc57604052565b610982565b906109d46109cd610273565b9283610998565b565b67ffffffffffffffff81116109ee5760208091020190565b610982565b600080fd5b90929192610a0d610a08826109d6565b6109c1565b9381855260208086019202830192818411610a4a57915b838310610a315750505050565b60208091610a3f848661039a565b815201920191610a24565b6109f3565b9080601f83011215610a6d57816020610a6a933591016109f8565b90565b610973565b67ffffffffffffffff8111610a8a5760208091020190565b610982565b90929192610aa4610a9f82610a72565b6109c1565b9381855260208086019202830192818411610ae157915b838310610ac85750505050565b60208091610ad68486610692565b815201920191610abb565b6109f3565b9080601f83011215610b0457816020610b0193359101610a8f565b90565b610973565b608081830312610b7c57610b20826000830161039a565b92602082013567ffffffffffffffff8111610b775783610b41918401610a4f565b9260408301359067ffffffffffffffff8211610b7257610b6681610b6f938601610ae6565b9360600161039a565b90565b610380565b610380565b61027e565b34610bb357610b9d610b94366004610b09565b929190916128dd565b610ba5610273565b80610baf81610347565b0390f35b610279565b7f000000000000000000000000000000000000000000000000000000000000000090565b610be5906103e7565b90565b610bf190610bdc565b9052565b9190610c0990600060208501940190610be8565b565b34610c3b57610c1b366004610283565b610c37610c26610bb8565b610c2e610273565b91829182610bf5565b0390f35b610279565b60001c90565b610c52610c5791610c40565b610417565b90565b610c649054610c46565b90565b600790610c826001610c7b60008501610c5a565b9301610c5a565b90565b34610cb657610c95366004610283565b610c9d610c67565b90610cb2610ca9610273565b92839283610766565b0390f35b610279565b610cc4816104b5565b03610ccb57565b600080fd5b90503590610cdd82610cbb565b565b9091606082840312610d1557610d12610cfb846000850161039a565b93610d098160208601610cd0565b93604001610692565b90565b61027e565b34610d4957610d33610d2d366004610cdf565b91612a0d565b610d3b610273565b80610d4581610347565b0390f35b610279565b34610d7d57610d67610d61366004610738565b90612aa0565b610d6f610273565b80610d7981610347565b0390f35b610279565b34610db457610d9b610d95366004610738565b90612e8e565b90610db0610da7610273565b92839283610766565b0390f35b610279565b34610de957610dc9366004610283565b610de5610dd4612eb2565b610ddc610273565b918291826102fc565b0390f35b610279565b7f000000000000000000000000000000000000000000000000000000000000000090565b610e1b906103e7565b90565b610e2790610e12565b9052565b9190610e3f90600060208501940190610e1e565b565b34610e7157610e51366004610283565b610e6d610e5c610dee565b610e64610273565b91829182610e2b565b0390f35b610279565b34610ea457610e8e610e893660046106a1565b613136565b610e96610273565b80610ea081610347565b0390f35b610279565b90565b610ec0610ebb610ec592610ea9565b6103c8565b61045a565b90565b610ed4620186a0610eac565b90565b610edf610ec8565b90565b34610f1257610ef2366004610283565b610f0e610efd610ed7565b610f05610273565b9182918261046a565b0390f35b610279565b6002610f2560008201610c5a565b91610f3e6002610f3760018501610c5a565b9301610c5a565b90565b604090610f6b610f729496959396610f616060840198600085019061045d565b602083019061045d565b019061045d565b565b34610fa757610f84366004610283565b610fa3610f8f610f17565b610f9a939193610273565b93849384610f41565b0390f35b610279565b610fb96009600090610432565b90565b34610fec57610fcc366004610283565b610fe8610fd7610fac565b610fdf610273565b9182918261046a565b0390f35b610279565b7f000000000000000000000000000000000000000000000000000000000000000090565b61101e906103e7565b90565b61102a90611015565b9052565b919061104290600060208501940190611021565b565b3461107457611054366004610283565b61107061105f610ff1565b611067610273565b9182918261102e565b0390f35b610279565b6080818303126110bb57611090826000830161039a565b926110b86110a1846020850161039a565b936110af8160408601610cd0565b93606001610692565b90565b61027e565b346110f4576110f06110df6110d6366004611079565b92919091613508565b6110e7610273565b9182918261046a565b0390f35b610279565b7f000000000000000000000000000000000000000000000000000000000000000090565b611126906103e7565b90565b6111329061111d565b9052565b919061114a90600060208501940190611129565b565b3461117c5761115c366004610283565b6111786111676110f9565b61116f610273565b91829182611136565b0390f35b610279565b60059061119c600161119560008501610c5a565b9301610c5a565b90565b346111d0576111af366004610283565b6111b7611181565b906111cc6111c3610273565b92839283610766565b0390f35b610279565b90565b6111ec6111e76111f1926111d5565b6103c8565b61045a565b90565b611205670de0b6b3a76400006111d8565b90565b6112106111f4565b90565b3461124357611223366004610283565b61123f61122e611208565b611236610273565b9182918261046a565b0390f35b610279565b346112765761126061125b3660046103a9565b61358d565b611268610273565b8061127281610347565b0390f35b610279565b346112a95761129361128e3660046106a1565b613608565b61129b610273565b806112a581610347565b0390f35b610279565b346112dc576112be366004610283565b6112c6613637565b6112ce610273565b806112d881610347565b0390f35b610279565b7f000000000000000000000000000000000000000000000000000000000000000090565b61130e906103e7565b90565b61131a90611305565b9052565b919061133290600060208501940190611311565b565b3461136457611344366004610283565b61136061134f6112e1565b611357610273565b9182918261131e565b0390f35b610279565b600080fd5b61137661366d565b61137e611388565b6113866136f8565b565b61139061370c565b50565b61139b61136e565b565b600090565b6113bf906113ae61139d565b506113b9600a610c5a565b90613869565b90565b6113d3906113ce61366d565b611599565b6113db6136f8565b565b600080fd5b60e01b90565b905051906113f58261067d565b565b906020828203126114115761140e916000016113e8565b90565b61027e565b604090611440611447949695939661143660608401986000850190611129565b602083019061045d565b01906104ba565b565b611451610273565b3d6000823e3d90fd5b634e487b7160e01b600052601160045260246000fd5b61147f6114859193929361045a565b9261045a565b820180921161149057565b61145a565b60001b90565b906114a860001991611495565b9181191691161790565b6114c66114c16114cb9261045a565b6103c8565b61045a565b90565b90565b906114e66114e16114ed926114b2565b6114ce565b825461149b565b9055565b919060408382031261151a578061150e61151792600086016113e8565b936020016113e8565b90565b61027e565b90565b61153661153161153b9261151f565b6103c8565b61045a565b90565b61154790611522565b9052565b90959492611597946115866115909261157c60809661157260a088019c6000890190611129565b60208701906102ef565b60408501906102ef565b606083019061045d565b019061153e565b565b6115c27f0000000000000000000000000000000000000000000000000000000000000000611305565b602063da5139ca917f00000000000000000000000000000000000000000000000000000000000000009061160a859461161560006115fe610273565b978896879586956113e2565b855260048501611416565b03915afa908115611806576000916117d8575b509061165982611653611644601061163e613a6e565b906103ff565b9161164e83610c5a565b611470565b906114d1565b611663600c610c5a565b611678611671828590611470565b600c6114d1565b60406116a37f0000000000000000000000000000000000000000000000000000000000000000611305565b6302b9446c906116fb60007f0000000000000000000000000000000000000000000000000000000000000000936117066116db613a6e565b986116e4613a6e565b9084916116ef610273565b9b8c998a9889976113e2565b87526004870161154b565b03925af19182156117d357611746926117a6575b507f00000000000000000000000000000000000000000000000000000000000000009083600092613a9f565b61174e613a6e565b90611757613a6e565b90916117a161178f6117897f8a844e786620b0b008b32c1151afb99261d854d9e0e911b2a5ee2f54bd5e3a0b936103f3565b936103f3565b93611798610273565b9182918261046a565b0390a3565b6117c69060403d81116117cc575b6117be8183610998565b8101906114f1565b5061171a565b503d6117b4565b611449565b6117f9915060203d81116117ff575b6117f18183610998565b8101906113f7565b38611628565b503d6117e7565b611449565b611814906113c2565b565b600090565b9061182f93929161182a61366d565b61183b565b90916118396136f8565b565b939161186193611850916118679381976118b1565b93909461185b61370c565b90613869565b156104b5565b61186d57565b611875610273565b63ff1847d560e01b81528061188c60048201610347565b0390fd5b61189c6118a191610c40565b61089b565b90565b6118ae9054611890565b90565b9291906118c66118c1600d6118a4565b6108dc565b6118df6118d96118d4613a6e565b6102e3565b916102e3565b036118f1576118ed9361191e565b9091565b61191a6118fc613a6e565b611904610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b90611934939291505061192f613d24565b613eda565b9091565b9061195391611945611816565b61194d611816565b9061181b565b9091565b9061196991611964614448565b6119d4565b565b61197560406109c1565b90565b906119829061045a565b9052565b611990905161045a565b90565b906119c0602060016119c6946119b8600082016119b260008801611986565b906114d1565b019201611986565b906114d1565b565b906119d291611993565b565b611a01816119fa846119f16119e761196b565b9360008501611978565b60208301611978565b60056119c8565b907f4549dc1c2e6edc0ddfb0530cc2a2be6db42a6bd6b6ad325244b41bb7d195376191611a38611a2f610273565b92839283610766565b0390a1565b90611a4791611957565b565b611a5a90611a5561366d565b611b13565b611a626136f8565b565b604090611a8e611a959496959396611a8460608401986000850190610e1e565b602083019061045d565b01906104ba565b565b6000910312611aa257565b61027e565b611ab0906103e7565b90565b611abf611ac491610c40565b610297565b90565b611ad19054611ab3565b90565b611b0a611b1194611b00606094989795611af6608086019a6000870190610e1e565b60208501906102ef565b60408301906102ef565b019061045d565b565b611b1b613a6e565b611b55611b4f611b4a7f0000000000000000000000000000000000000000000000000000000000000000611015565b6102e3565b916102e3565b03611e2057611b62613d24565b611b6f6001600201610c5a565b90611b997f0000000000000000000000000000000000000000000000000000000000000000611305565b602063da5139ca917f000000000000000000000000000000000000000000000000000000000000000090611be18694611bec6000611bd5610273565b978896879586956113e2565b855260048501611a64565b03915afa908115611e1b57600091611ded575b5090611c18611c0e6000611522565b60016002016114d1565b611c417f000000000000000000000000000000000000000000000000000000000000000061057b565b90632e2ebe0690823b15611de857611c7992611c6e60008094611c62610273565b968795869485936113e2565b83526004830161046a565b03925af18015611de357611db6575b50611cb27f0000000000000000000000000000000000000000000000000000000000000000611305565b63f18d03cc907f000000000000000000000000000000000000000000000000000000000000000090611ce330611aa7565b93611cee600e611ac7565b90823b15611db157600094611d218692611d1694611d0a610273565b998a98899788966113e2565b865260048601611ad4565b03925af18015611dac57611d7f575b50611d3b600e611ac7565b611d7a611d687fc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a926103f3565b92611d71610273565b9182918261046a565b0390a2565b611d9f9060003d8111611da5575b611d978183610998565b810190611a97565b38611d30565b503d611d8d565b611449565b6113dd565b611dd69060003d8111611ddc575b611dce8183610998565b810190611a97565b38611c88565b503d611dc4565b611449565b6113dd565b611e0e915060203d8111611e14575b611e068183610998565b8101906113f7565b38611bff565b503d611dfc565b611449565b611e49611e2b613a6e565b611e33610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b611e5690611a49565b565b611e60614448565b611e68611e92565b565b611e7e611e79611e839261151f565b6103c8565b6102d8565b90565b611e8f90611e6a565b90565b611ea4611e9f6000611e86565b6144db565b565b611eae611e58565b565b90611ec4939291611ebf61366d565b611ece565b611ecc6136f8565b565b929190611ee3611ede600d6118a4565b6108dc565b611efc611ef6611ef1613a6e565b6102e3565b916102e3565b03611f0c57611f0a93612195565b565b611f35611f17613a6e565b611f1f610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b600080fd5b9190604083820312611f7a57611f7390611f5860406109c1565b93611f6682600083016113e8565b60008601526020016113e8565b6020830152565b611f39565b90604082820312611f9957611f9691600001611f3e565b90565b61027e565b5190565b6001611fae910161045a565b90565b634e487b7160e01b600052603260045260246000fd5b90611fd182611f9e565b811015611fe2576020809102010190565b611fb1565b611ff190516102e3565b90565b5190565b9061200282611ff4565b811015612013576020809102010190565b611fb1565b61202260406109c1565b90565b9061205e6120556001612036612018565b9461204f61204660008301610c5a565b60008801611978565b01610c5a565b60208401611978565b565b61206990612025565b90565b61207b6120819193929361045a565b9261045a565b9161208d83820261045a565b92818404149015171561209c57565b61145a565b634e487b7160e01b600052601260045260246000fd5b6120c36120c99161045a565b9161045a565b9081156120d4570490565b6120a1565b6120e86120ee9193929361045a565b9261045a565b82039182116120f957565b61145a565b90565b61211561211061211a926120fe565b6103c8565b61045a565b90565b612127600a612101565b90565b90565b61214161213c6121469261212a565b6103c8565b61045a565b90565b612153606461212d565b90565b61218c61219394612182606094989795612178608086019a6000870190611129565b60208501906102ef565b60408301906102ef565b019061045d565b565b929061219f61370c565b926121a8613d24565b6121b26000611522565b906121bd6000611522565b936121c86000611522565b9661224160406121f77f0000000000000000000000000000000000000000000000000000000000000000611305565b634ffe34db906122367f00000000000000000000000000000000000000000000000000000000000000009261222a610273565b958694859384936113e2565b835260048301611136565b03915afa9081156128d8576000916128aa575b509461225f81611f9e565b99612268611816565b5b8b61227d612277839261045a565b9161045a565b101561251457612296612291848390611fc7565b611fe7565b6122aa6122a4828d90613869565b156104b5565b6122be575b506122b990611fa2565b612269565b988a9760009c929c506122cf611816565b506122e46122df600f8d906103ff565b610c5a565b8d6122f86122f38b8390611ff8565b611986565b61230a6123048461045a565b9161045a565b116000146124fd5750805b809c600761232290612060565b8260009061232f92614559565b9b8d908d61233d600b610c5a565b6123469161206c565b7f00000000000000000000000000000000000000000000000000000000000000006123709161206c565b9061237a916120b7565b612382610ec8565b61238b916120b7565b6000906123979261462d565b92826123a2916120d9565b600f826123ae916103ff565b906123b8916114d1565b826010826123c5916103ff565b906123cf82610c5a565b906123d9916120d9565b6123e2916114d1565b808a84917fce4d55ad6d5734bd8b947e19d64c51774bdc08ab4b2e59ee3a764476bea650de90612411906103f3565b9161241b906103f3565b92612424610273565b61242f81928261046a565b0390a388818d9184927fe62a777dbd48d3912f68a1b9445813ee02bc3ac18b97dc129ca462cc77bb641b91612463906103f3565b9261246d906103f3565b93612476610273565b9182916124839183610766565b0390a3899083928d7fae8ca5a29805f6680885140b89042d3a7ffca73fff143ac6f48e398d05902bbb926124b6906103f3565b936124c0906103f3565b946124c9610273565b9283926124d69284610f41565b0390a36124e291611470565b976124ec91611470565b986124f691611470565b99386122af565b61250a61250f918b611ff8565b611986565b612315565b5099505094935095919450508161253461252e6000611522565b9161045a565b146128875761257b9061255e8361255860006007019161255383610c5a565b6120d9565b906114d1565b61257560016007019161257083610c5a565b6120d9565b906114d1565b6125986125918461258c600c610c5a565b6120d9565b600c6114d1565b6126156125f76125ef6125e16125d36125cc6125be876125b8600b610c5a565b9061206c565b6125c6610ec8565b906120b7565b86906120d9565b6125db61211d565b9061206c565b6125e9612149565b906120b7565b928390611470565b9161260f60016002019161260a83610c5a565b611470565b906114d1565b60206126407f0000000000000000000000000000000000000000000000000000000000000000611305565b9163da5139ca926126867f00000000000000000000000000000000000000000000000000000000000000009294612691600161267a610273565b978896879586956113e2565b855260048501611a64565b03915afa90811561288257600091612854575b50906126cf7f0000000000000000000000000000000000000000000000000000000000000000611305565b9063f18d03cc917f0000000000000000000000000000000000000000000000000000000000000000919361270230611aa7565b90823b1561284f57600094612735869261272a9461271e610273565b998a98899788966113e2565b865260048601611ad4565b03925af1801561284a5761281d575b5061276e7f0000000000000000000000000000000000000000000000000000000000000000611305565b9063f18d03cc917f0000000000000000000000000000000000000000000000000000000000000000916127a030611aa7565b9490823b15612818576000946127d486926127c9946127bd610273565b998a98899788966113e2565b865260048601612156565b03925af18015612813576127e6575b50565b6128069060003d811161280c575b6127fe8183610998565b810190611a97565b386127e3565b503d6127f4565b611449565b6113dd565b61283d9060003d8111612843575b6128358183610998565b810190611a97565b38612744565b503d61282b565b611449565b6113dd565b612875915060203d811161287b575b61286d8183610998565b8101906113f7565b386126a4565b503d612863565b611449565b61288f610273565b63342ac43760e01b8152806128a660048201610347565b0390fd5b6128cb915060403d81116128d1575b6128c38183610998565b810190611f7f565b38612254565b503d6128b9565b611449565b906128e9939291611eb0565b565b906128fe92916128f961366d565b612908565b6129066136f8565b565b91906129328261292c61291d601087906103ff565b9161292783610c5a565b611470565b906114d1565b61297e61293f600c610c5a565b61295461294d828690611470565b600c6114d1565b7f000000000000000000000000000000000000000000000000000000000000000090848492613a9f565b6000146129ff576129ae7f0000000000000000000000000000000000000000000000000000000000000000611305565b915b90916129fa6129e86129e27f8a844e786620b0b008b32c1151afb99261d854d9e0e911b2a5ee2f54bd5e3a0b936103f3565b936103f3565b936129f1610273565b9182918261046a565b0390a3565b612a07613a6e565b916129b0565b90612a1892916128eb565b565b90612a2c91612a2761366d565b612a36565b612a346136f8565b565b612a5d90612a4f612a6393612a49613a6e565b92612a8c565b612a5761370c565b90613869565b156104b5565b612a6957565b612a71610273565b63ff1847d560e01b815280612a8860048201610347565b0390fd5b90612a9e91612a99613d24565b614701565b565b90612aaa91612a1a565b565b90612ac0939291612abb61366d565b612acc565b9091612aca6136f8565b565b9391612af293612ae191612af8938197612b21565b939094612aec61370c565b90613869565b156104b5565b612afe57565b612b06610273565b63ff1847d560e01b815280612b1d60048201610347565b0390fd5b929190612b36612b31600d6118a4565b6108dc565b612b4f612b49612b44613a6e565b6102e3565b916102e3565b03612b6157612b5d93612c00565b9091565b612b8a612b6c613a6e565b612b74610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b916020612bb0929493612ba960408201966000830190610e1e565b01906102ef565b565b90959492612bfe94612bed612bf792612be3608096612bd960a088019c6000890190610e1e565b60208701906102ef565b60408501906102ef565b606083019061045d565b019061153e565b565b939192935050612c0e613d24565b612c19828490613eda565b929093612c457f0000000000000000000000000000000000000000000000000000000000000000611305565b6356623118917f0000000000000000000000000000000000000000000000000000000000000000612c957f0000000000000000000000000000000000000000000000000000000000000000611305565b92602063f7888aec947f000000000000000000000000000000000000000000000000000000000000000090612cdc8997612ce7612cd0610273565b998a95869485946113e2565b845260048401612b8e565b03915afa938415612e8957600094612e53575b50612d1c6020939495612d276000612d10610273565b988996879586956113e2565b855260048501611a64565b03915afa8015612e4e57604092600091612e20575b5080612d50612d4a8461045a565b9161045a565b11600014612e1957505b612d837f0000000000000000000000000000000000000000000000000000000000000000611305565b612dca60006397da6d30612dd57f00000000000000000000000000000000000000000000000000000000000000009588908491612dbe610273565b9a8b998a9889976113e2565b875260048701612bb2565b03925af18015612e1457612de7575b50565b612e079060403d8111612e0d575b612dff8183610998565b8101906114f1565b50612de4565b503d612df5565b611449565b9050612d5a565b612e41915060203d8111612e47575b612e398183610998565b8101906113f7565b38612d3c565b503d612e2f565b611449565b6020939450612e7a612d1c91853d8111612e82575b612e728183610998565b8101906113f7565b949350612cfa565b503d612e68565b611449565b90612ea991612e9b611816565b612ea3611816565b90612aac565b9091565b600090565b612eba612ead565b50612ec56000611ac7565b90565b612ed990612ed461366d565b612ee3565b612ee16136f8565b565b612f09612f0f91612efb612ef5613a6e565b91612f86565b612f0361370c565b90613869565b156104b5565b612f1557565b612f1d610273565b63ff1847d560e01b815280612f3460048201610347565b0390fd5b90959492612f8494612f73612f7d92612f69608096612f5f60a088019c6000890190611129565b60208701906102ef565b60408501906102ef565b606083019061153e565b019061045d565b565b6020612fb17f0000000000000000000000000000000000000000000000000000000000000000611305565b9163da5139ca92612ff77f000000000000000000000000000000000000000000000000000000000000000092946130026000612feb610273565b978896879586956113e2565b855260048501611416565b03915afa90811561313157600091613103575b5061301e613d24565b613030613029613a6e565b8290614701565b604061305b7f0000000000000000000000000000000000000000000000000000000000000000611305565b6397da6d30906130b460007f0000000000000000000000000000000000000000000000000000000000000000936130bf613093613a6e565b9761309c613a6e565b908490916130a8610273565b9a8b998a9889976113e2565b875260048701612f38565b03925af180156130fe576130d1575b50565b6130f19060403d81116130f7575b6130e98183610998565b8101906114f1565b506130ce565b503d6130df565b611449565b613124915060203d811161312a575b61311c8183610998565b8101906113f7565b38613015565b503d613112565b611449565b61313f90612ec8565b565b906131569493929161315161366d565b613161565b9061315f6136f8565b565b93929190613177613172600d6118a4565b6108dc565b61319061318a613185613a6e565b6102e3565b916102e3565b036131a15761319e9461320f565b90565b6131ca6131ac613a6e565b6131b4610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b906131fb60206001613201946131f3600082016131ed60008801611986565b906114d1565b019201611986565b906114d1565b565b9061320d916131ce565b565b9261323e9594935061321f613d24565b61323561322c6007612060565b856001916148b2565b96906007613203565b8361326461325e613259613254600f88906103ff565b610c5a565b61045a565b9161045a565b116134ec575b6132928461328c61327d600f87906103ff565b9161328783610c5a565b6120d9565b906114d1565b6132bb7f0000000000000000000000000000000000000000000000000000000000000000611305565b602063da5139ca917f0000000000000000000000000000000000000000000000000000000000000000906133038a9461330e60016132f7610273565b978896879586956113e2565b855260048501611a64565b03915afa9081156134e7576000916134b9575b5061334b7f0000000000000000000000000000000000000000000000000000000000000000611305565b63f18d03cc907f000000000000000000000000000000000000000000000000000000000000000090846000146134b2576133a47f0000000000000000000000000000000000000000000000000000000000000000611305565b935b6133af30611aa7565b90823b156134ad576000946133e286926133d7946133cb610273565b998a98899788966113e2565b865260048601611ad4565b03925af180156134a85761347b575b5060001461347557506134237f0000000000000000000000000000000000000000000000000000000000000000611305565b905b90849261345b6134557fe62a777dbd48d3912f68a1b9445813ee02bc3ac18b97dc129ca462cc77bb641b936103f3565b936103f3565b93613470613467610273565b92839283610766565b0390a3565b90613425565b61349b9060003d81116134a1575b6134938183610998565b810190611a97565b386133f1565b503d613489565b611449565b6113dd565b85936133a6565b6134da915060203d81116134e0575b6134d28183610998565b8101906113f7565b38613321565b503d6134c8565b611449565b92506135026134fd600f84906103ff565b610c5a565b9261326a565b9061351c939291613517611816565b613141565b90565b6135309061352b614448565b613532565b565b8061354e6135486135436000611e86565b6102e3565b916102e3565b1461355e5761355c906144db565b565b61358961356b6000611e86565b613573610273565b91829163b20f76e360e01b8352600483016102fc565b0390fd5b6135969061351f565b565b6135a9906135a4614448565b6135ab565b565b6135b760028001610c5a565b6135bf613d24565b6135cc82600280016114d1565b907ff93ce1b2e2cb74b524760dff1842e28b944e9c40627c07348a36c404be739c02916136036135fa610273565b92839283610766565b0390a1565b61361190613598565b565b61361b61366d565b61362361362d565b61362b6136f8565b565b613635613d24565b565b61363f613613565b565b90565b61365861365361365d92613641565b6103c8565b61045a565b90565b61366a6002613644565b90565b6136776001610c5a565b61369061368a613685613660565b61045a565b9161045a565b146136a9576136a76136a0613660565b60016114d1565b565b6136b1610273565b6306fda65d60e31b8152806136c860048201610347565b0390fd5b90565b6136e36136de6136e8926136cc565b6103c8565b61045a565b90565b6136f560016136cf565b90565b61370a6137036136eb565b60016114d1565b565b613714611816565b5061379560206137437f0000000000000000000000000000000000000000000000000000000000000000610bdc565b6341976e099061378a6137757f000000000000000000000000000000000000000000000000000000000000000061111d565b9261377e610273565b958694859384936113e2565b8352600483016102fc565b03915afa90811561386457600091613836575b50806137bd6137b76000611522565b9161045a565b14613813576137cd81600a6114d1565b6138037f8bc87b062b954eccd7f9017a070917f40c9c40af9ff4b41ed4f52a6a37199276916137fa610273565b9182918261046a565b0390a1613810600a610c5a565b90565b61381b610273565b632a208a1f60e01b81528061383260048201610347565b0390fd5b613857915060203d811161385d575b61384f8183610998565b8101906113f7565b386137a8565b503d613845565b611449565b9061387261139d565b5061389a61389561388d613888600f86906103ff565b610c5a565b9360106103ff565b610c5a565b91806138af6138a96000611522565b9161045a565b146000146138bf57505050600190565b826138d36138cd6000611522565b9161045a565b146000146138e357505050600090565b6138ed6007612060565b9060206139197f0000000000000000000000000000000000000000000000000000000000000000611305565b9463566231189561398361396961395b7f0000000000000000000000000000000000000000000000000000000000000000946139556009610c5a565b9061206c565b613963610ec8565b906120b7565b9761398e6000613977610273565b9a8b96879586956113e2565b855260048501611416565b03915afa938415613a6957600094613a17575b50613a1292613a02613a0c936139fc60206139f56139ce613a07976139c860008701611986565b9061206c565b7f00000000000000000000000000000000000000000000000000000000000000009061206c565b9201611986565b906120b7565b6120b7565b61045a565b9161045a565b101590565b613a0791945092613a02613a0c936139fc60206139f56139ce613a52613a129a843d8111613a62575b613a4a8183610998565b8101906113f7565b9a975050505050935050926139a1565b503d613a40565b611449565b613a76612ead565b503390565b916020613a9d929493613a9660408201966000830190611129565b01906102ef565b565b9192600014613b9b57916020613ad47f0000000000000000000000000000000000000000000000000000000000000000611305565b63f7888aec9390613aff613ae730611aa7565b95613b0a613af3610273565b978895869485946113e2565b845260048401613a7b565b03915afa918215613b9657613b3b92613b3592613b3092600092613b66575b50906120d9565b61045a565b9161045a565b11613b43575b565b613b4b610273565b633551b94d60e01b815280613b6260048201610347565b0390fd5b613b8891925060203d8111613b8f575b613b808183610998565b8101906113f7565b9038613b29565b503d613b76565b611449565b9150613bc67f0000000000000000000000000000000000000000000000000000000000000000611305565b63f18d03cc9190613bd5613a6e565b93613bdf30611aa7565b90823b15613c5957600094613c128692613c0794613bfb610273565b998a98899788966113e2565b865260048601612156565b03925af18015613c5457613c27575b50613b41565b613c479060003d8111613c4d575b613c3f8183610998565b810190611a97565b38613c21565b503d613c35565b611449565b6113dd565b613c6860606109c1565b90565b90613cbc613cb36002613c7c613c5e565b94613c95613c8c60008301610c5a565b60008801611978565b613cad613ca460018301610c5a565b60208801611978565b01610c5a565b60408401611978565b565b613cc790613c6b565b90565b90613d1060406002613d1694613cef60008201613ce960008801611986565b906114d1565b613d0860018201613d0260208801611986565b906114d1565b019201611986565b906114d1565b565b90613d2291613cca565b565b613d2e6002613cbe565b613d4442613d3e60008401611986565b906120d9565b9081613d59613d536000611522565b9161045a565b14613e8257613d686007612060565b91613d7560208401611986565b613d88613d826000611522565b9161045a565b14613e665790613df7613dcf613dc1613e2b94613dbc613daa60008901611986565b613db660408801611986565b9061206c565b61206c565b613dc96111f4565b906120b7565b93613df085613dea6000840191613de583611986565b611470565b90611978565b6007613203565b613e1783613e116020840191613e0c83611986565b611470565b90611978565b613e244260008301611978565b6002613d18565b613e617ff3486c8be7415104f077b000d812e60c482b6824642b7673b3f73d6faeca29a691613e58610273565b9182918261046a565b0390a1565b50613e809150613e794260008301611978565b6002613d18565b565b5050565b613e9060406109c1565b90565b90613ecc613ec36001613ea4613e86565b94613ebd613eb460008301610c5a565b60008801611978565b01610c5a565b60208401611978565b565b613ed790613e93565b90565b91613f1092613ee7611816565b50613ef0611816565b50613f07613efe6007612060565b84600191614919565b94906007613203565b613f1a6005613ece565b613f276000600701610c5a565b613f44613f3e613f3960008501611986565b61045a565b9161045a565b1161442557613f67613f60613f5b600f85906103ff565b610c5a565b8690611470565b90613f86613f80613f7b6020859401611986565b61045a565b9161045a565b1161440257613fa090613f9b600f84906103ff565b6114d1565b613fc97f0000000000000000000000000000000000000000000000000000000000000000611305565b6356623118907f00000000000000000000000000000000000000000000000000000000000000006140197f0000000000000000000000000000000000000000000000000000000000000000611305565b91602063f7888aec937f00000000000000000000000000000000000000000000000000000000000000009061406861405030611aa7565b9661407361405c610273565b988995869485946113e2565b845260048401612b8e565b03915afa9283156143fd576000936143c9575b506140a7602093946140b2600061409b610273565b978896879586956113e2565b855260048501611a64565b03915afa9081156143c457600091614396575b506140ce611816565b50836140e26140dc8361045a565b9161045a565b11600014614386576140f490846120d9565b5b61411e7f000000000000000000000000000000000000000000000000000000000000000061057b565b90632e2ebe0690823b15614381576141569261414b6000809461413f610273565b968795869485936113e2565b83526004830161046a565b03925af1801561437c5761434f575b5061418f7f0000000000000000000000000000000000000000000000000000000000000000611305565b602063da5139ca917f0000000000000000000000000000000000000000000000000000000000000000906141d787946141e260006141cb610273565b978896879586956113e2565b855260048501611a64565b03915afa90811561434a5760009161431c575b50926142207f0000000000000000000000000000000000000000000000000000000000000000611305565b63f18d03cc7f000000000000000000000000000000000000000000000000000000000000000061424f30611aa7565b928588823b156143175760009461428486926142799461426d610273565b998a98899788966113e2565b865260048601611ad4565b03925af18015614312576142e5575b50819091856142cb6142c57fc14e9e6b4d98a542b05a0f6b64acd5f4cbdb914be88432d87486b664e97071a7936103f3565b936103f3565b936142e06142d7610273565b92839283610766565b0390a3565b6143059060003d811161430b575b6142fd8183610998565b810190611a97565b38614293565b503d6142f3565b611449565b6113dd565b61433d915060203d8111614343575b6143358183610998565b8101906113f7565b386141f5565b503d61432b565b611449565b61436f9060003d8111614375575b6143678183610998565b810190611a97565b38614165565b503d61435d565b611449565b6113dd565b506143916000611522565b6140f5565b6143b7915060203d81116143bd575b6143af8183610998565b8101906113f7565b386140c5565b503d6143a5565b611449565b602093506143ef6140a791853d81116143f6575b6143e78183610998565b8101906113f7565b9350614086565b503d6143dd565b611449565b61440a610273565b632eb0ae9960e11b81528061442160048201610347565b0390fd5b61442d610273565b632eb0ae9960e11b81528061444460048201610347565b0390fd5b614450612eb2565b61446961446361445e613a6e565b6102e3565b916102e3565b0361447057565b61449961447b613a6e565b614483610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b906144ae60018060a01b0391611495565b9181191691161790565b90565b906144d06144cb6144d7926103f3565b6144b8565b825461449d565b9055565b6144e56000611ac7565b6144f08260006144bb565b9061452461451e7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0936103f3565b916103f3565b9161452d610273565b8061453781610347565b0390a3565b6145459061045a565b60001981146145545760010190565b61145a565b919091614564611816565b5061457160208201611986565b61458461457e6000611522565b9161045a565b14600014614592575050905b565b9092916145c06145ae826145a860008601611986565b9061206c565b6145ba60208501611986565b906120b7565b9391826145e4575b50506145d4575b614590565b906145de9061453c565b906145cf565b61462591925061461961461f91614613600061460c8961460660208601611986565b9061206c565b9201611986565b906120b7565b9261045a565b9161045a565b1038806145c8565b919091614638611816565b5061464560008201611986565b6146586146526000611522565b9161045a565b14600014614666575050905b565b9092916146946146828261467c60208601611986565b9061206c565b61468e60008501611986565b906120b7565b9391826146b8575b50506146a8575b614664565b906146b29061453c565b906146a3565b6146f99192506146ed6146f3916146e760206146e0896146da60008601611986565b9061206c565b9201611986565b906120b7565b9261045a565b9161045a565b10388061469c565b906147318161472b61471c6010614716613a6e565b906103ff565b9161472683610c5a565b6120d9565b906114d1565b61474e61474782614742600c610c5a565b6120d9565b600c6114d1565b614756613a6e565b8282916147a161478f6147897fce4d55ad6d5734bd8b947e19d64c51774bdc08ab4b2e59ee3a764476bea650de936103f3565b936103f3565b93614798610273565b9182918261046a565b0390a36147cd7f0000000000000000000000000000000000000000000000000000000000000000611305565b9063f18d03cc917f0000000000000000000000000000000000000000000000000000000000000000916147ff30611aa7565b9490823b156148775760009461483386926148289461481c610273565b998a98899788966113e2565b865260048601612156565b03925af1801561487257614845575b50565b6148659060003d811161486b575b61485d8183610998565b810190611a97565b38614842565b503d614853565b611449565b6113dd565b600090565b614889612018565b906020808361489661487c565b8152016148a161487c565b81525050565b6148af614881565b90565b9092916148d8614915916148c46148a7565b506148cd611816565b508390869091614559565b936148f9856148f360008601916148ee83611986565b6120d9565b90611978565b61490f602084019161490a83611986565b6120d9565b90611978565b9190565b90929161493f61495c9161492b6148a7565b50614934611816565b50839086909161462d565b93614956600084019161495183611986565b611470565b90611978565b61497c83614976602084019161497183611986565b611470565b90611978565b919056fea26469706673582212204baa6769be6344a6d2307db4cb96cd29d0d21166faa470e71f6ff9d3cb2dd07364736f6c634300081800330000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e0000000000000000000000000000000000000000000000000000000000017ed00000000000000000000000000000000000000000000000000000000000018a88
Deployed Bytecode
0x60806040526004361015610013575b611369565b61001e60003561026d565b8063017e7e581461026857806302ce728f146102635780631c9e379b1461025e57806338b51ce1146102595780633ba0b9a9146102545780633d5064191461024f578063430aea2e1461024a578063473e3ce7146102455780634886cf321461024057806348e4163e1461023b5780634b8a3529146102365780634c343f0014610231578063529898f21461022c5780635e318e071461022757806363b0e66a14610222578063715018a61461021d5780637ce69001146102185780637dc0d1d0146102135780638285ef401461020e578063860ffea114610209578063876467f8146102045780638a1bdb54146101ff5780638da5cb5b146101fa57806396df10c0146101f55780639b821418146101f0578063ad3b55ce146101eb578063b27c0e74146101e6578063b4eae1cb146101e1578063cbfd73d5146101dc578063cd0211eb146101d7578063d8dfeb45146101d2578063e551d11d146101cd578063f23c0f40146101c8578063f2fde38b146101c3578063f5d93f52146101be578063f8ba4cff146101b95763fbfa77cf0361000e57611334565b6112ae565b61127b565b611248565b611213565b61119f565b61114c565b6110c0565b611044565b610fbc565b610f74565b610ee2565b610e76565b610e41565b610db9565b610d82565b610d4e565b610d1a565b610c85565b610c0b565b610b81565b610940565b61090b565b610868565b610833565b6107ef565b61078a565b610703565b6106c0565b610648565b610603565b6105aa565b610522565b6104dd565b610480565b61034d565b610312565b60e01c90565b60405190565b600080fd5b600080fd5b600091031261028e57565b61027e565b1c90565b60018060a01b031690565b6102b29060086102b79302610293565b610297565b90565b906102c591546102a2565b90565b6102d5600e6000906102ba565b90565b60018060a01b031690565b6102ec906102d8565b90565b6102f8906102e3565b9052565b9190610310906000602085019401906102ef565b565b3461034257610322366004610283565b61033e61032d6102c8565b610335610273565b918291826102fc565b0390f35b610279565b60000190565b3461037b5761035d366004610283565b610365611393565b61036d610273565b8061037781610347565b0390f35b610279565b600080fd5b61038e816102e3565b0361039557565b600080fd5b905035906103a782610385565b565b906020828203126103c3576103c09160000161039a565b90565b61027e565b90565b6103df6103da6103e4926102d8565b6103c8565b6102d8565b90565b6103f0906103cb565b90565b6103fc906103e7565b90565b90610409906103f3565b600052602052604060002090565b90565b61042a90600861042f9302610293565b610417565b90565b9061043d915461041a565b90565b610457906104526010916000926103ff565b610432565b90565b90565b6104669061045a565b9052565b919061047e9060006020850194019061045d565b565b346104b0576104ac61049b6104963660046103a9565b610440565b6104a3610273565b9182918261046a565b0390f35b610279565b151590565b6104c3906104b5565b9052565b91906104db906000602085019401906104ba565b565b3461050d576105096104f86104f33660046103a9565b6113a2565b610500610273565b918291826104c7565b0390f35b610279565b61051f600a600090610432565b90565b3461055257610532366004610283565b61054e61053d610512565b610545610273565b9182918261046a565b0390f35b610279565b7f0000000000000000000000000893131746962b4b5afb573351ba7f4094d81aad90565b610584906103e7565b90565b6105909061057b565b9052565b91906105a890600060208501940190610587565b565b346105da576105ba366004610283565b6105d66105c5610557565b6105cd610273565b91829182610594565b0390f35b610279565b7f0000000000000000000000000000000000000000000000000de0b6b3a764000090565b3461063357610613366004610283565b61062f61061e6105df565b610626610273565b9182918261046a565b0390f35b610279565b610645600c600090610432565b90565b3461067857610658366004610283565b610674610663610638565b61066b610273565b9182918261046a565b0390f35b610279565b6106868161045a565b0361068d57565b600080fd5b9050359061069f8261067d565b565b906020828203126106bb576106b891600001610692565b90565b61027e565b6106d36106ce3660046106a1565b61180b565b6106db610273565b806106e581610347565b0390f35b610700906106fb600f916000926103ff565b610432565b90565b346107335761072f61071e6107193660046103a9565b6106e9565b610726610273565b9182918261046a565b0390f35b610279565b9190604083820312610761578061075561075e926000860161039a565b93602001610692565b90565b61027e565b9160206107889294936107816040820196600083019061045d565b019061045d565b565b346107bc576107a361079d366004610738565b90611938565b906107b86107af610273565b92839283610766565b0390f35b610279565b91906040838203126107ea57806107de6107e79260008601610692565b93602001610692565b90565b61027e565b3461081e576108086108023660046107c1565b90611a3d565b610810610273565b8061081a81610347565b0390f35b610279565b610830600b600090610432565b90565b3461086357610843366004610283565b61085f61084e610823565b610856610273565b9182918261046a565b0390f35b610279565b346108965761088061087b3660046106a1565b611e4d565b610888610273565b8061089281610347565b0390f35b610279565b60018060a01b031690565b6108b69060086108bb9302610293565b61089b565b90565b906108c991546108a6565b90565b6108d9600d6000906108be565b90565b6108e5906103e7565b90565b6108f1906108dc565b9052565b9190610909906000602085019401906108e8565b565b3461093b5761091b366004610283565b6109376109266108cc565b61092e610273565b918291826108f5565b0390f35b610279565b3461096e57610950366004610283565b610958611ea6565b610960610273565b8061096a81610347565b0390f35b610279565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b906109a290610978565b810190811067ffffffffffffffff8211176109bc57604052565b610982565b906109d46109cd610273565b9283610998565b565b67ffffffffffffffff81116109ee5760208091020190565b610982565b600080fd5b90929192610a0d610a08826109d6565b6109c1565b9381855260208086019202830192818411610a4a57915b838310610a315750505050565b60208091610a3f848661039a565b815201920191610a24565b6109f3565b9080601f83011215610a6d57816020610a6a933591016109f8565b90565b610973565b67ffffffffffffffff8111610a8a5760208091020190565b610982565b90929192610aa4610a9f82610a72565b6109c1565b9381855260208086019202830192818411610ae157915b838310610ac85750505050565b60208091610ad68486610692565b815201920191610abb565b6109f3565b9080601f83011215610b0457816020610b0193359101610a8f565b90565b610973565b608081830312610b7c57610b20826000830161039a565b92602082013567ffffffffffffffff8111610b775783610b41918401610a4f565b9260408301359067ffffffffffffffff8211610b7257610b6681610b6f938601610ae6565b9360600161039a565b90565b610380565b610380565b61027e565b34610bb357610b9d610b94366004610b09565b929190916128dd565b610ba5610273565b80610baf81610347565b0390f35b610279565b7f00000000000000000000000019b3a42bfbd4452e6a2b92b2e898916b68cb713f90565b610be5906103e7565b90565b610bf190610bdc565b9052565b9190610c0990600060208501940190610be8565b565b34610c3b57610c1b366004610283565b610c37610c26610bb8565b610c2e610273565b91829182610bf5565b0390f35b610279565b60001c90565b610c52610c5791610c40565b610417565b90565b610c649054610c46565b90565b600790610c826001610c7b60008501610c5a565b9301610c5a565b90565b34610cb657610c95366004610283565b610c9d610c67565b90610cb2610ca9610273565b92839283610766565b0390f35b610279565b610cc4816104b5565b03610ccb57565b600080fd5b90503590610cdd82610cbb565b565b9091606082840312610d1557610d12610cfb846000850161039a565b93610d098160208601610cd0565b93604001610692565b90565b61027e565b34610d4957610d33610d2d366004610cdf565b91612a0d565b610d3b610273565b80610d4581610347565b0390f35b610279565b34610d7d57610d67610d61366004610738565b90612aa0565b610d6f610273565b80610d7981610347565b0390f35b610279565b34610db457610d9b610d95366004610738565b90612e8e565b90610db0610da7610273565b92839283610766565b0390f35b610279565b34610de957610dc9366004610283565b610de5610dd4612eb2565b610ddc610273565b918291826102fc565b0390f35b610279565b7f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f85490565b610e1b906103e7565b90565b610e2790610e12565b9052565b9190610e3f90600060208501940190610e1e565b565b34610e7157610e51366004610283565b610e6d610e5c610dee565b610e64610273565b91829182610e2b565b0390f35b610279565b34610ea457610e8e610e893660046106a1565b613136565b610e96610273565b80610ea081610347565b0390f35b610279565b90565b610ec0610ebb610ec592610ea9565b6103c8565b61045a565b90565b610ed4620186a0610eac565b90565b610edf610ec8565b90565b34610f1257610ef2366004610283565b610f0e610efd610ed7565b610f05610273565b9182918261046a565b0390f35b610279565b6002610f2560008201610c5a565b91610f3e6002610f3760018501610c5a565b9301610c5a565b90565b604090610f6b610f729496959396610f616060840198600085019061045d565b602083019061045d565b019061045d565b565b34610fa757610f84366004610283565b610fa3610f8f610f17565b610f9a939193610273565b93849384610f41565b0390f35b610279565b610fb96009600090610432565b90565b34610fec57610fcc366004610283565b610fe8610fd7610fac565b610fdf610273565b9182918261046a565b0390f35b610279565b7f0000000000000000000000001efd8d6b72843a70fe194f29de94fc3c5b5f9e9790565b61101e906103e7565b90565b61102a90611015565b9052565b919061104290600060208501940190611021565b565b3461107457611054366004610283565b61107061105f610ff1565b611067610273565b9182918261102e565b0390f35b610279565b6080818303126110bb57611090826000830161039a565b926110b86110a1846020850161039a565b936110af8160408601610cd0565b93606001610692565b90565b61027e565b346110f4576110f06110df6110d6366004611079565b92919091613508565b6110e7610273565b9182918261046a565b0390f35b610279565b7f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e90565b611126906103e7565b90565b6111329061111d565b9052565b919061114a90600060208501940190611129565b565b3461117c5761115c366004610283565b6111786111676110f9565b61116f610273565b91829182611136565b0390f35b610279565b60059061119c600161119560008501610c5a565b9301610c5a565b90565b346111d0576111af366004610283565b6111b7611181565b906111cc6111c3610273565b92839283610766565b0390f35b610279565b90565b6111ec6111e76111f1926111d5565b6103c8565b61045a565b90565b611205670de0b6b3a76400006111d8565b90565b6112106111f4565b90565b3461124357611223366004610283565b61123f61122e611208565b611236610273565b9182918261046a565b0390f35b610279565b346112765761126061125b3660046103a9565b61358d565b611268610273565b8061127281610347565b0390f35b610279565b346112a95761129361128e3660046106a1565b613608565b61129b610273565b806112a581610347565b0390f35b610279565b346112dc576112be366004610283565b6112c6613637565b6112ce610273565b806112d881610347565b0390f35b610279565b7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf90565b61130e906103e7565b90565b61131a90611305565b9052565b919061133290600060208501940190611311565b565b3461136457611344366004610283565b61136061134f6112e1565b611357610273565b9182918261131e565b0390f35b610279565b600080fd5b61137661366d565b61137e611388565b6113866136f8565b565b61139061370c565b50565b61139b61136e565b565b600090565b6113bf906113ae61139d565b506113b9600a610c5a565b90613869565b90565b6113d3906113ce61366d565b611599565b6113db6136f8565b565b600080fd5b60e01b90565b905051906113f58261067d565b565b906020828203126114115761140e916000016113e8565b90565b61027e565b604090611440611447949695939661143660608401986000850190611129565b602083019061045d565b01906104ba565b565b611451610273565b3d6000823e3d90fd5b634e487b7160e01b600052601160045260246000fd5b61147f6114859193929361045a565b9261045a565b820180921161149057565b61145a565b60001b90565b906114a860001991611495565b9181191691161790565b6114c66114c16114cb9261045a565b6103c8565b61045a565b90565b90565b906114e66114e16114ed926114b2565b6114ce565b825461149b565b9055565b919060408382031261151a578061150e61151792600086016113e8565b936020016113e8565b90565b61027e565b90565b61153661153161153b9261151f565b6103c8565b61045a565b90565b61154790611522565b9052565b90959492611597946115866115909261157c60809661157260a088019c6000890190611129565b60208701906102ef565b60408501906102ef565b606083019061045d565b019061153e565b565b6115c27f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b602063da5139ca917f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e9061160a859461161560006115fe610273565b978896879586956113e2565b855260048501611416565b03915afa908115611806576000916117d8575b509061165982611653611644601061163e613a6e565b906103ff565b9161164e83610c5a565b611470565b906114d1565b611663600c610c5a565b611678611671828590611470565b600c6114d1565b60406116a37f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b6302b9446c906116fb60007f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e936117066116db613a6e565b986116e4613a6e565b9084916116ef610273565b9b8c998a9889976113e2565b87526004870161154b565b03925af19182156117d357611746926117a6575b507f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e9083600092613a9f565b61174e613a6e565b90611757613a6e565b90916117a161178f6117897f8a844e786620b0b008b32c1151afb99261d854d9e0e911b2a5ee2f54bd5e3a0b936103f3565b936103f3565b93611798610273565b9182918261046a565b0390a3565b6117c69060403d81116117cc575b6117be8183610998565b8101906114f1565b5061171a565b503d6117b4565b611449565b6117f9915060203d81116117ff575b6117f18183610998565b8101906113f7565b38611628565b503d6117e7565b611449565b611814906113c2565b565b600090565b9061182f93929161182a61366d565b61183b565b90916118396136f8565b565b939161186193611850916118679381976118b1565b93909461185b61370c565b90613869565b156104b5565b61186d57565b611875610273565b63ff1847d560e01b81528061188c60048201610347565b0390fd5b61189c6118a191610c40565b61089b565b90565b6118ae9054611890565b90565b9291906118c66118c1600d6118a4565b6108dc565b6118df6118d96118d4613a6e565b6102e3565b916102e3565b036118f1576118ed9361191e565b9091565b61191a6118fc613a6e565b611904610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b90611934939291505061192f613d24565b613eda565b9091565b9061195391611945611816565b61194d611816565b9061181b565b9091565b9061196991611964614448565b6119d4565b565b61197560406109c1565b90565b906119829061045a565b9052565b611990905161045a565b90565b906119c0602060016119c6946119b8600082016119b260008801611986565b906114d1565b019201611986565b906114d1565b565b906119d291611993565b565b611a01816119fa846119f16119e761196b565b9360008501611978565b60208301611978565b60056119c8565b907f4549dc1c2e6edc0ddfb0530cc2a2be6db42a6bd6b6ad325244b41bb7d195376191611a38611a2f610273565b92839283610766565b0390a1565b90611a4791611957565b565b611a5a90611a5561366d565b611b13565b611a626136f8565b565b604090611a8e611a959496959396611a8460608401986000850190610e1e565b602083019061045d565b01906104ba565b565b6000910312611aa257565b61027e565b611ab0906103e7565b90565b611abf611ac491610c40565b610297565b90565b611ad19054611ab3565b90565b611b0a611b1194611b00606094989795611af6608086019a6000870190610e1e565b60208501906102ef565b60408301906102ef565b019061045d565b565b611b1b613a6e565b611b55611b4f611b4a7f0000000000000000000000001efd8d6b72843a70fe194f29de94fc3c5b5f9e97611015565b6102e3565b916102e3565b03611e2057611b62613d24565b611b6f6001600201610c5a565b90611b997f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b602063da5139ca917f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f85490611be18694611bec6000611bd5610273565b978896879586956113e2565b855260048501611a64565b03915afa908115611e1b57600091611ded575b5090611c18611c0e6000611522565b60016002016114d1565b611c417f0000000000000000000000000893131746962b4b5afb573351ba7f4094d81aad61057b565b90632e2ebe0690823b15611de857611c7992611c6e60008094611c62610273565b968795869485936113e2565b83526004830161046a565b03925af18015611de357611db6575b50611cb27f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b63f18d03cc907f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f85490611ce330611aa7565b93611cee600e611ac7565b90823b15611db157600094611d218692611d1694611d0a610273565b998a98899788966113e2565b865260048601611ad4565b03925af18015611dac57611d7f575b50611d3b600e611ac7565b611d7a611d687fc0819c13be868895eb93e40eaceb96de976442fa1d404e5c55f14bb65a8c489a926103f3565b92611d71610273565b9182918261046a565b0390a2565b611d9f9060003d8111611da5575b611d978183610998565b810190611a97565b38611d30565b503d611d8d565b611449565b6113dd565b611dd69060003d8111611ddc575b611dce8183610998565b810190611a97565b38611c88565b503d611dc4565b611449565b6113dd565b611e0e915060203d8111611e14575b611e068183610998565b8101906113f7565b38611bff565b503d611dfc565b611449565b611e49611e2b613a6e565b611e33610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b611e5690611a49565b565b611e60614448565b611e68611e92565b565b611e7e611e79611e839261151f565b6103c8565b6102d8565b90565b611e8f90611e6a565b90565b611ea4611e9f6000611e86565b6144db565b565b611eae611e58565b565b90611ec4939291611ebf61366d565b611ece565b611ecc6136f8565b565b929190611ee3611ede600d6118a4565b6108dc565b611efc611ef6611ef1613a6e565b6102e3565b916102e3565b03611f0c57611f0a93612195565b565b611f35611f17613a6e565b611f1f610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b600080fd5b9190604083820312611f7a57611f7390611f5860406109c1565b93611f6682600083016113e8565b60008601526020016113e8565b6020830152565b611f39565b90604082820312611f9957611f9691600001611f3e565b90565b61027e565b5190565b6001611fae910161045a565b90565b634e487b7160e01b600052603260045260246000fd5b90611fd182611f9e565b811015611fe2576020809102010190565b611fb1565b611ff190516102e3565b90565b5190565b9061200282611ff4565b811015612013576020809102010190565b611fb1565b61202260406109c1565b90565b9061205e6120556001612036612018565b9461204f61204660008301610c5a565b60008801611978565b01610c5a565b60208401611978565b565b61206990612025565b90565b61207b6120819193929361045a565b9261045a565b9161208d83820261045a565b92818404149015171561209c57565b61145a565b634e487b7160e01b600052601260045260246000fd5b6120c36120c99161045a565b9161045a565b9081156120d4570490565b6120a1565b6120e86120ee9193929361045a565b9261045a565b82039182116120f957565b61145a565b90565b61211561211061211a926120fe565b6103c8565b61045a565b90565b612127600a612101565b90565b90565b61214161213c6121469261212a565b6103c8565b61045a565b90565b612153606461212d565b90565b61218c61219394612182606094989795612178608086019a6000870190611129565b60208501906102ef565b60408301906102ef565b019061045d565b565b929061219f61370c565b926121a8613d24565b6121b26000611522565b906121bd6000611522565b936121c86000611522565b9661224160406121f77f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b634ffe34db906122367f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e9261222a610273565b958694859384936113e2565b835260048301611136565b03915afa9081156128d8576000916128aa575b509461225f81611f9e565b99612268611816565b5b8b61227d612277839261045a565b9161045a565b101561251457612296612291848390611fc7565b611fe7565b6122aa6122a4828d90613869565b156104b5565b6122be575b506122b990611fa2565b612269565b988a9760009c929c506122cf611816565b506122e46122df600f8d906103ff565b610c5a565b8d6122f86122f38b8390611ff8565b611986565b61230a6123048461045a565b9161045a565b116000146124fd5750805b809c600761232290612060565b8260009061232f92614559565b9b8d908d61233d600b610c5a565b6123469161206c565b7f0000000000000000000000000000000000000000000000000de0b6b3a76400006123709161206c565b9061237a916120b7565b612382610ec8565b61238b916120b7565b6000906123979261462d565b92826123a2916120d9565b600f826123ae916103ff565b906123b8916114d1565b826010826123c5916103ff565b906123cf82610c5a565b906123d9916120d9565b6123e2916114d1565b808a84917fce4d55ad6d5734bd8b947e19d64c51774bdc08ab4b2e59ee3a764476bea650de90612411906103f3565b9161241b906103f3565b92612424610273565b61242f81928261046a565b0390a388818d9184927fe62a777dbd48d3912f68a1b9445813ee02bc3ac18b97dc129ca462cc77bb641b91612463906103f3565b9261246d906103f3565b93612476610273565b9182916124839183610766565b0390a3899083928d7fae8ca5a29805f6680885140b89042d3a7ffca73fff143ac6f48e398d05902bbb926124b6906103f3565b936124c0906103f3565b946124c9610273565b9283926124d69284610f41565b0390a36124e291611470565b976124ec91611470565b986124f691611470565b99386122af565b61250a61250f918b611ff8565b611986565b612315565b5099505094935095919450508161253461252e6000611522565b9161045a565b146128875761257b9061255e8361255860006007019161255383610c5a565b6120d9565b906114d1565b61257560016007019161257083610c5a565b6120d9565b906114d1565b6125986125918461258c600c610c5a565b6120d9565b600c6114d1565b6126156125f76125ef6125e16125d36125cc6125be876125b8600b610c5a565b9061206c565b6125c6610ec8565b906120b7565b86906120d9565b6125db61211d565b9061206c565b6125e9612149565b906120b7565b928390611470565b9161260f60016002019161260a83610c5a565b611470565b906114d1565b60206126407f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b9163da5139ca926126867f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f8549294612691600161267a610273565b978896879586956113e2565b855260048501611a64565b03915afa90811561288257600091612854575b50906126cf7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b9063f18d03cc917f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f854919361270230611aa7565b90823b1561284f57600094612735869261272a9461271e610273565b998a98899788966113e2565b865260048601611ad4565b03925af1801561284a5761281d575b5061276e7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b9063f18d03cc917f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e916127a030611aa7565b9490823b15612818576000946127d486926127c9946127bd610273565b998a98899788966113e2565b865260048601612156565b03925af18015612813576127e6575b50565b6128069060003d811161280c575b6127fe8183610998565b810190611a97565b386127e3565b503d6127f4565b611449565b6113dd565b61283d9060003d8111612843575b6128358183610998565b810190611a97565b38612744565b503d61282b565b611449565b6113dd565b612875915060203d811161287b575b61286d8183610998565b8101906113f7565b386126a4565b503d612863565b611449565b61288f610273565b63342ac43760e01b8152806128a660048201610347565b0390fd5b6128cb915060403d81116128d1575b6128c38183610998565b810190611f7f565b38612254565b503d6128b9565b611449565b906128e9939291611eb0565b565b906128fe92916128f961366d565b612908565b6129066136f8565b565b91906129328261292c61291d601087906103ff565b9161292783610c5a565b611470565b906114d1565b61297e61293f600c610c5a565b61295461294d828690611470565b600c6114d1565b7f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e90848492613a9f565b6000146129ff576129ae7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b915b90916129fa6129e86129e27f8a844e786620b0b008b32c1151afb99261d854d9e0e911b2a5ee2f54bd5e3a0b936103f3565b936103f3565b936129f1610273565b9182918261046a565b0390a3565b612a07613a6e565b916129b0565b90612a1892916128eb565b565b90612a2c91612a2761366d565b612a36565b612a346136f8565b565b612a5d90612a4f612a6393612a49613a6e565b92612a8c565b612a5761370c565b90613869565b156104b5565b612a6957565b612a71610273565b63ff1847d560e01b815280612a8860048201610347565b0390fd5b90612a9e91612a99613d24565b614701565b565b90612aaa91612a1a565b565b90612ac0939291612abb61366d565b612acc565b9091612aca6136f8565b565b9391612af293612ae191612af8938197612b21565b939094612aec61370c565b90613869565b156104b5565b612afe57565b612b06610273565b63ff1847d560e01b815280612b1d60048201610347565b0390fd5b929190612b36612b31600d6118a4565b6108dc565b612b4f612b49612b44613a6e565b6102e3565b916102e3565b03612b6157612b5d93612c00565b9091565b612b8a612b6c613a6e565b612b74610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b916020612bb0929493612ba960408201966000830190610e1e565b01906102ef565b565b90959492612bfe94612bed612bf792612be3608096612bd960a088019c6000890190610e1e565b60208701906102ef565b60408501906102ef565b606083019061045d565b019061153e565b565b939192935050612c0e613d24565b612c19828490613eda565b929093612c457f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b6356623118917f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f854612c957f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b92602063f7888aec947f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f85490612cdc8997612ce7612cd0610273565b998a95869485946113e2565b845260048401612b8e565b03915afa938415612e8957600094612e53575b50612d1c6020939495612d276000612d10610273565b988996879586956113e2565b855260048501611a64565b03915afa8015612e4e57604092600091612e20575b5080612d50612d4a8461045a565b9161045a565b11600014612e1957505b612d837f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b612dca60006397da6d30612dd57f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f8549588908491612dbe610273565b9a8b998a9889976113e2565b875260048701612bb2565b03925af18015612e1457612de7575b50565b612e079060403d8111612e0d575b612dff8183610998565b8101906114f1565b50612de4565b503d612df5565b611449565b9050612d5a565b612e41915060203d8111612e47575b612e398183610998565b8101906113f7565b38612d3c565b503d612e2f565b611449565b6020939450612e7a612d1c91853d8111612e82575b612e728183610998565b8101906113f7565b949350612cfa565b503d612e68565b611449565b90612ea991612e9b611816565b612ea3611816565b90612aac565b9091565b600090565b612eba612ead565b50612ec56000611ac7565b90565b612ed990612ed461366d565b612ee3565b612ee16136f8565b565b612f09612f0f91612efb612ef5613a6e565b91612f86565b612f0361370c565b90613869565b156104b5565b612f1557565b612f1d610273565b63ff1847d560e01b815280612f3460048201610347565b0390fd5b90959492612f8494612f73612f7d92612f69608096612f5f60a088019c6000890190611129565b60208701906102ef565b60408501906102ef565b606083019061153e565b019061045d565b565b6020612fb17f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b9163da5139ca92612ff77f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e92946130026000612feb610273565b978896879586956113e2565b855260048501611416565b03915afa90811561313157600091613103575b5061301e613d24565b613030613029613a6e565b8290614701565b604061305b7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b6397da6d30906130b460007f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e936130bf613093613a6e565b9761309c613a6e565b908490916130a8610273565b9a8b998a9889976113e2565b875260048701612f38565b03925af180156130fe576130d1575b50565b6130f19060403d81116130f7575b6130e98183610998565b8101906114f1565b506130ce565b503d6130df565b611449565b613124915060203d811161312a575b61311c8183610998565b8101906113f7565b38613015565b503d613112565b611449565b61313f90612ec8565b565b906131569493929161315161366d565b613161565b9061315f6136f8565b565b93929190613177613172600d6118a4565b6108dc565b61319061318a613185613a6e565b6102e3565b916102e3565b036131a15761319e9461320f565b90565b6131ca6131ac613a6e565b6131b4610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b906131fb60206001613201946131f3600082016131ed60008801611986565b906114d1565b019201611986565b906114d1565b565b9061320d916131ce565b565b9261323e9594935061321f613d24565b61323561322c6007612060565b856001916148b2565b96906007613203565b8361326461325e613259613254600f88906103ff565b610c5a565b61045a565b9161045a565b116134ec575b6132928461328c61327d600f87906103ff565b9161328783610c5a565b6120d9565b906114d1565b6132bb7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b602063da5139ca917f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f854906133038a9461330e60016132f7610273565b978896879586956113e2565b855260048501611a64565b03915afa9081156134e7576000916134b9575b5061334b7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b63f18d03cc907f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f85490846000146134b2576133a47f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b935b6133af30611aa7565b90823b156134ad576000946133e286926133d7946133cb610273565b998a98899788966113e2565b865260048601611ad4565b03925af180156134a85761347b575b5060001461347557506134237f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b905b90849261345b6134557fe62a777dbd48d3912f68a1b9445813ee02bc3ac18b97dc129ca462cc77bb641b936103f3565b936103f3565b93613470613467610273565b92839283610766565b0390a3565b90613425565b61349b9060003d81116134a1575b6134938183610998565b810190611a97565b386133f1565b503d613489565b611449565b6113dd565b85936133a6565b6134da915060203d81116134e0575b6134d28183610998565b8101906113f7565b38613321565b503d6134c8565b611449565b92506135026134fd600f84906103ff565b610c5a565b9261326a565b9061351c939291613517611816565b613141565b90565b6135309061352b614448565b613532565b565b8061354e6135486135436000611e86565b6102e3565b916102e3565b1461355e5761355c906144db565b565b61358961356b6000611e86565b613573610273565b91829163b20f76e360e01b8352600483016102fc565b0390fd5b6135969061351f565b565b6135a9906135a4614448565b6135ab565b565b6135b760028001610c5a565b6135bf613d24565b6135cc82600280016114d1565b907ff93ce1b2e2cb74b524760dff1842e28b944e9c40627c07348a36c404be739c02916136036135fa610273565b92839283610766565b0390a1565b61361190613598565b565b61361b61366d565b61362361362d565b61362b6136f8565b565b613635613d24565b565b61363f613613565b565b90565b61365861365361365d92613641565b6103c8565b61045a565b90565b61366a6002613644565b90565b6136776001610c5a565b61369061368a613685613660565b61045a565b9161045a565b146136a9576136a76136a0613660565b60016114d1565b565b6136b1610273565b6306fda65d60e31b8152806136c860048201610347565b0390fd5b90565b6136e36136de6136e8926136cc565b6103c8565b61045a565b90565b6136f560016136cf565b90565b61370a6137036136eb565b60016114d1565b565b613714611816565b5061379560206137437f00000000000000000000000019b3a42bfbd4452e6a2b92b2e898916b68cb713f610bdc565b6341976e099061378a6137757f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e61111d565b9261377e610273565b958694859384936113e2565b8352600483016102fc565b03915afa90811561386457600091613836575b50806137bd6137b76000611522565b9161045a565b14613813576137cd81600a6114d1565b6138037f8bc87b062b954eccd7f9017a070917f40c9c40af9ff4b41ed4f52a6a37199276916137fa610273565b9182918261046a565b0390a1613810600a610c5a565b90565b61381b610273565b632a208a1f60e01b81528061383260048201610347565b0390fd5b613857915060203d811161385d575b61384f8183610998565b8101906113f7565b386137a8565b503d613845565b611449565b9061387261139d565b5061389a61389561388d613888600f86906103ff565b610c5a565b9360106103ff565b610c5a565b91806138af6138a96000611522565b9161045a565b146000146138bf57505050600190565b826138d36138cd6000611522565b9161045a565b146000146138e357505050600090565b6138ed6007612060565b9060206139197f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b9463566231189561398361396961395b7f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e946139556009610c5a565b9061206c565b613963610ec8565b906120b7565b9761398e6000613977610273565b9a8b96879586956113e2565b855260048501611416565b03915afa938415613a6957600094613a17575b50613a1292613a02613a0c936139fc60206139f56139ce613a07976139c860008701611986565b9061206c565b7f0000000000000000000000000000000000000000000000000de0b6b3a76400009061206c565b9201611986565b906120b7565b6120b7565b61045a565b9161045a565b101590565b613a0791945092613a02613a0c936139fc60206139f56139ce613a52613a129a843d8111613a62575b613a4a8183610998565b8101906113f7565b9a975050505050935050926139a1565b503d613a40565b611449565b613a76612ead565b503390565b916020613a9d929493613a9660408201966000830190611129565b01906102ef565b565b9192600014613b9b57916020613ad47f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b63f7888aec9390613aff613ae730611aa7565b95613b0a613af3610273565b978895869485946113e2565b845260048401613a7b565b03915afa918215613b9657613b3b92613b3592613b3092600092613b66575b50906120d9565b61045a565b9161045a565b11613b43575b565b613b4b610273565b633551b94d60e01b815280613b6260048201610347565b0390fd5b613b8891925060203d8111613b8f575b613b808183610998565b8101906113f7565b9038613b29565b503d613b76565b611449565b9150613bc67f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b63f18d03cc9190613bd5613a6e565b93613bdf30611aa7565b90823b15613c5957600094613c128692613c0794613bfb610273565b998a98899788966113e2565b865260048601612156565b03925af18015613c5457613c27575b50613b41565b613c479060003d8111613c4d575b613c3f8183610998565b810190611a97565b38613c21565b503d613c35565b611449565b6113dd565b613c6860606109c1565b90565b90613cbc613cb36002613c7c613c5e565b94613c95613c8c60008301610c5a565b60008801611978565b613cad613ca460018301610c5a565b60208801611978565b01610c5a565b60408401611978565b565b613cc790613c6b565b90565b90613d1060406002613d1694613cef60008201613ce960008801611986565b906114d1565b613d0860018201613d0260208801611986565b906114d1565b019201611986565b906114d1565b565b90613d2291613cca565b565b613d2e6002613cbe565b613d4442613d3e60008401611986565b906120d9565b9081613d59613d536000611522565b9161045a565b14613e8257613d686007612060565b91613d7560208401611986565b613d88613d826000611522565b9161045a565b14613e665790613df7613dcf613dc1613e2b94613dbc613daa60008901611986565b613db660408801611986565b9061206c565b61206c565b613dc96111f4565b906120b7565b93613df085613dea6000840191613de583611986565b611470565b90611978565b6007613203565b613e1783613e116020840191613e0c83611986565b611470565b90611978565b613e244260008301611978565b6002613d18565b613e617ff3486c8be7415104f077b000d812e60c482b6824642b7673b3f73d6faeca29a691613e58610273565b9182918261046a565b0390a1565b50613e809150613e794260008301611978565b6002613d18565b565b5050565b613e9060406109c1565b90565b90613ecc613ec36001613ea4613e86565b94613ebd613eb460008301610c5a565b60008801611978565b01610c5a565b60208401611978565b565b613ed790613e93565b90565b91613f1092613ee7611816565b50613ef0611816565b50613f07613efe6007612060565b84600191614919565b94906007613203565b613f1a6005613ece565b613f276000600701610c5a565b613f44613f3e613f3960008501611986565b61045a565b9161045a565b1161442557613f67613f60613f5b600f85906103ff565b610c5a565b8690611470565b90613f86613f80613f7b6020859401611986565b61045a565b9161045a565b1161440257613fa090613f9b600f84906103ff565b6114d1565b613fc97f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b6356623118907f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f8546140197f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b91602063f7888aec937f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f8549061406861405030611aa7565b9661407361405c610273565b988995869485946113e2565b845260048401612b8e565b03915afa9283156143fd576000936143c9575b506140a7602093946140b2600061409b610273565b978896879586956113e2565b855260048501611a64565b03915afa9081156143c457600091614396575b506140ce611816565b50836140e26140dc8361045a565b9161045a565b11600014614386576140f490846120d9565b5b61411e7f0000000000000000000000000893131746962b4b5afb573351ba7f4094d81aad61057b565b90632e2ebe0690823b15614381576141569261414b6000809461413f610273565b968795869485936113e2565b83526004830161046a565b03925af1801561437c5761434f575b5061418f7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b602063da5139ca917f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f854906141d787946141e260006141cb610273565b978896879586956113e2565b855260048501611a64565b03915afa90811561434a5760009161431c575b50926142207f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b63f18d03cc7f000000000000000000000000e30e73cc52ef50a4e4a8b1a3dd0b002b2276f85461424f30611aa7565b928588823b156143175760009461428486926142799461426d610273565b998a98899788966113e2565b865260048601611ad4565b03925af18015614312576142e5575b50819091856142cb6142c57fc14e9e6b4d98a542b05a0f6b64acd5f4cbdb914be88432d87486b664e97071a7936103f3565b936103f3565b936142e06142d7610273565b92839283610766565b0390a3565b6143059060003d811161430b575b6142fd8183610998565b810190611a97565b38614293565b503d6142f3565b611449565b6113dd565b61433d915060203d8111614343575b6143358183610998565b8101906113f7565b386141f5565b503d61432b565b611449565b61436f9060003d8111614375575b6143678183610998565b810190611a97565b38614165565b503d61435d565b611449565b6113dd565b506143916000611522565b6140f5565b6143b7915060203d81116143bd575b6143af8183610998565b8101906113f7565b386140c5565b503d6143a5565b611449565b602093506143ef6140a791853d81116143f6575b6143e78183610998565b8101906113f7565b9350614086565b503d6143dd565b611449565b61440a610273565b632eb0ae9960e11b81528061442160048201610347565b0390fd5b61442d610273565b632eb0ae9960e11b81528061444460048201610347565b0390fd5b614450612eb2565b61446961446361445e613a6e565b6102e3565b916102e3565b0361447057565b61449961447b613a6e565b614483610273565b9182916332b2baa360e01b8352600483016102fc565b0390fd5b906144ae60018060a01b0391611495565b9181191691161790565b90565b906144d06144cb6144d7926103f3565b6144b8565b825461449d565b9055565b6144e56000611ac7565b6144f08260006144bb565b9061452461451e7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0936103f3565b916103f3565b9161452d610273565b8061453781610347565b0390a3565b6145459061045a565b60001981146145545760010190565b61145a565b919091614564611816565b5061457160208201611986565b61458461457e6000611522565b9161045a565b14600014614592575050905b565b9092916145c06145ae826145a860008601611986565b9061206c565b6145ba60208501611986565b906120b7565b9391826145e4575b50506145d4575b614590565b906145de9061453c565b906145cf565b61462591925061461961461f91614613600061460c8961460660208601611986565b9061206c565b9201611986565b906120b7565b9261045a565b9161045a565b1038806145c8565b919091614638611816565b5061464560008201611986565b6146586146526000611522565b9161045a565b14600014614666575050905b565b9092916146946146828261467c60208601611986565b9061206c565b61468e60008501611986565b906120b7565b9391826146b8575b50506146a8575b614664565b906146b29061453c565b906146a3565b6146f99192506146ed6146f3916146e760206146e0896146da60008601611986565b9061206c565b9201611986565b906120b7565b9261045a565b9161045a565b10388061469c565b906147318161472b61471c6010614716613a6e565b906103ff565b9161472683610c5a565b6120d9565b906114d1565b61474e61474782614742600c610c5a565b6120d9565b600c6114d1565b614756613a6e565b8282916147a161478f6147897fce4d55ad6d5734bd8b947e19d64c51774bdc08ab4b2e59ee3a764476bea650de936103f3565b936103f3565b93614798610273565b9182918261046a565b0390a36147cd7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf611305565b9063f18d03cc917f0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e916147ff30611aa7565b9490823b156148775760009461483386926148289461481c610273565b998a98899788966113e2565b865260048601612156565b03925af1801561487257614845575b50565b6148659060003d811161486b575b61485d8183610998565b810190611a97565b38614842565b503d614853565b611449565b6113dd565b600090565b614889612018565b906020808361489661487c565b8152016148a161487c565b81525050565b6148af614881565b90565b9092916148d8614915916148c46148a7565b506148cd611816565b508390869091614559565b936148f9856148f360008601916148ee83611986565b6120d9565b90611978565b61490f602084019161490a83611986565b6120d9565b90611978565b9190565b90929161493f61495c9161492b6148a7565b50614934611816565b50839086909161462d565b93614956600084019161495183611986565b611470565b90611978565b61497c83614976602084019161497183611986565b611470565b90611978565b919056fea26469706673582212204baa6769be6344a6d2307db4cb96cd29d0d21166faa470e71f6ff9d3cb2dd07364736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e0000000000000000000000000000000000000000000000000000000000017ed00000000000000000000000000000000000000000000000000000000000018a88
-----Decoded View---------------
Arg [0] : baseContracts_ (address): 0x5Ce899AEd04c656776148fc3b1Adbe59e5f13D5c
Arg [1] : collateral_ (address): 0x8221312e9cF90A2B160eCdabf922408a5ef1CF9E
Arg [2] : collateralRatio_ (uint256): 98000
Arg [3] : liquidationMultiplier_ (uint256): 101000
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000005ce899aed04c656776148fc3b1adbe59e5f13d5c
Arg [1] : 0000000000000000000000008221312e9cf90a2b160ecdabf922408a5ef1cf9e
Arg [2] : 0000000000000000000000000000000000000000000000000000000000017ed0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000018a88
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.