Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
9779380 | 20 hrs ago | Contract Creation | 0 S |
Loading...
Loading
Contract Name:
ControllerTimelockV3
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {PolicyManagerV3} from "./PolicyManagerV3.sol"; import {IControllerTimelockV3, QueuedTransactionData} from "../interfaces/IControllerTimelockV3.sol"; import {ICreditManagerV3} from "../interfaces/ICreditManagerV3.sol"; import {ICreditFacadeV3} from "../interfaces/ICreditFacadeV3.sol"; import {IPoolV3} from "../interfaces/IPoolV3.sol"; import {IPoolQuotaKeeperV3} from "../interfaces/IPoolQuotaKeeperV3.sol"; import {IGaugeV3} from "../interfaces/IGaugeV3.sol"; import {ILPPriceFeedV2} from "@gearbox-protocol/core-v2/contracts/interfaces/ILPPriceFeedV2.sol"; import "../interfaces/IExceptions.sol"; /// @title Controller timelock V3 /// @notice Controller timelock is a governance contract that allows special actors less trusted than Gearbox Governance /// to modify system parameters within set boundaries. This is mostly related to risk parameters that should be /// adjusted frequently or periodic tasks (e.g., updating price feed limiters) that are too trivial to employ /// the full governance for. /// @dev The contract uses `PolicyManager` as its underlying engine to set parameter change boundaries and conditions. /// In order to schedule a change for a particular contract / function combination, a policy needs to be defined /// for it. The policy also determines the address that can change a particular parameter. contract ControllerTimelockV3 is PolicyManagerV3, IControllerTimelockV3 { /// @notice Contract version uint256 public constant override version = 3_00; /// @dev Minimum liquidation threshold ramp duration uint256 constant MIN_LT_RAMP_DURATION = 7 days; /// @notice Period before a mature transaction becomes stale uint256 public constant override GRACE_PERIOD = 14 days; /// @notice Admin address that can cancel transactions address public override vetoAdmin; /// @notice Mapping from transaction hashes to their data mapping(bytes32 => QueuedTransactionData) public override queuedTransactions; /// @notice Constructor /// @param _addressProvider Address of the address provider /// @param _vetoAdmin Admin that can cancel transactions constructor(address _addressProvider, address _vetoAdmin) PolicyManagerV3(_addressProvider) { vetoAdmin = _vetoAdmin; } /// @dev Ensures that function caller is the veto admin modifier vetoAdminOnly() { _revertIfCallerIsNotVetoAdmin(); _; } /// @dev Reverts if `msg.sender` is not the veto admin function _revertIfCallerIsNotVetoAdmin() internal view { if (msg.sender != vetoAdmin) { revert CallerNotVetoAdminException(); } } // -------- // // QUEUEING // // -------- // /// @notice Queues a transaction to set a new expiration date in the Credit Facade /// @dev Requires the policy for keccak(group(creditManager), "EXPIRATION_DATE") to be enabled, /// otherwise auto-fails the check /// @param creditManager Adress of CM to update the expiration date for /// @param expirationDate The new expiration date function setExpirationDate(address creditManager, uint40 expirationDate) external override { address creditConfigurator = ICreditManagerV3(creditManager).creditConfigurator(); IPoolV3 pool = IPoolV3(ICreditManagerV3(creditManager).pool()); address creditFacade = ICreditManagerV3(creditManager).creditFacade(); uint40 oldExpirationDate = getExpirationDate(creditFacade); if (!_checkPolicy(creditManager, "EXPIRATION_DATE", uint256(oldExpirationDate), uint256(expirationDate))) { revert ParameterChecksFailedException(); // U:[CT-1] } uint256 totalBorrowed = pool.creditManagerBorrowed(address(creditManager)); if (totalBorrowed != 0) { revert ParameterChecksFailedException(); // U:[CT-1] } _queueTransaction({ target: creditConfigurator, signature: "setExpirationDate(uint40)", data: abi.encode(expirationDate), delay: _getPolicyDelay(creditManager, "EXPIRATION_DATE"), sanityCheckValue: oldExpirationDate, sanityCheckCallData: abi.encodeCall(this.getExpirationDate, (creditFacade)) }); // U:[CT-1] } /// @dev Retrieves current expiration date for a credit manager function getExpirationDate(address creditFacade) public view returns (uint40) { return ICreditFacadeV3(creditFacade).expirationDate(); } /// @notice Queues a transaction to set a new limiter value in a price feed /// @dev Requires the policy for keccak(group(priceFeed), "LP_PRICE_FEED_LIMITER") to be enabled, /// otherwise auto-fails the check /// @param priceFeed The price feed to update the limiter in /// @param lowerBound The new limiter lower bound value function setLPPriceFeedLimiter(address priceFeed, uint256 lowerBound) external override { uint256 currentLowerBound = getPriceFeedLowerBound(priceFeed); if (!_checkPolicy(priceFeed, "LP_PRICE_FEED_LIMITER", currentLowerBound, lowerBound)) { revert ParameterChecksFailedException(); // U:[CT-2] } _queueTransaction({ target: priceFeed, signature: "setLimiter(uint256)", data: abi.encode(lowerBound), delay: _getPolicyDelay(priceFeed, "LP_PRICE_FEED_LIMITER"), sanityCheckValue: currentLowerBound, sanityCheckCallData: abi.encodeCall(this.getPriceFeedLowerBound, (priceFeed)) }); // U:[CT-2] } /// @dev Retrieves current lower bound for a price feed function getPriceFeedLowerBound(address priceFeed) public view returns (uint256) { return ILPPriceFeedV2(priceFeed).lowerBound(); } /// @notice Queues a transaction to set a new max debt per block multiplier /// @dev Requires the policy for keccak(group(creditManager), "MAX_DEBT_PER_BLOCK_MULTIPLIER") to be enabled, /// otherwise auto-fails the check /// @param creditManager Adress of CM to update the multiplier for /// @param multiplier The new multiplier value function setMaxDebtPerBlockMultiplier(address creditManager, uint8 multiplier) external override { address creditConfigurator = ICreditManagerV3(creditManager).creditConfigurator(); address creditFacade = ICreditManagerV3(creditManager).creditFacade(); uint8 currentMultiplier = getMaxDebtPerBlockMultiplier(creditFacade); if ( !_checkPolicy( creditManager, "MAX_DEBT_PER_BLOCK_MULTIPLIER", uint256(currentMultiplier), uint256(multiplier) ) ) { revert ParameterChecksFailedException(); // U:[CT-3] } _queueTransaction({ target: creditConfigurator, signature: "setMaxDebtPerBlockMultiplier(uint8)", data: abi.encode(multiplier), delay: _getPolicyDelay(creditManager, "MAX_DEBT_PER_BLOCK_MULTIPLIER"), sanityCheckValue: currentMultiplier, sanityCheckCallData: abi.encodeCall(this.getMaxDebtPerBlockMultiplier, (creditFacade)) }); // U:[CT-3] } /// @dev Retrieves current max debt per block multiplier for a Credit Facade function getMaxDebtPerBlockMultiplier(address creditFacade) public view returns (uint8) { return ICreditFacadeV3(creditFacade).maxDebtPerBlockMultiplier(); } /// @notice Queues a transaction to set a new min debt per account /// @dev Requires the policy for keccak(group(creditManager), "MIN_DEBT") to be enabled, /// otherwise auto-fails the check /// @param creditManager Adress of CM to update the limits for /// @param minDebt The new minimal debt amount function setMinDebtLimit(address creditManager, uint128 minDebt) external override { address creditConfigurator = ICreditManagerV3(creditManager).creditConfigurator(); address creditFacade = ICreditManagerV3(creditManager).creditFacade(); uint128 minDebtCurrent = getMinDebtLimit(creditFacade); if (!_checkPolicy(creditManager, "MIN_DEBT", uint256(minDebtCurrent), uint256(minDebt))) { revert ParameterChecksFailedException(); // U:[CT-4A] } _queueTransaction({ target: creditConfigurator, signature: "setMinDebtLimit(uint128)", data: abi.encode(minDebt), delay: _getPolicyDelay(creditManager, "MIN_DEBT"), sanityCheckValue: minDebtCurrent, sanityCheckCallData: abi.encodeCall(this.getMinDebtLimit, (creditFacade)) }); // U:[CT-4A] } /// @dev Retrieves the current min debt limit for a Credit Manager function getMinDebtLimit(address creditFacade) public view returns (uint128) { (uint128 minDebtCurrent,) = ICreditFacadeV3(creditFacade).debtLimits(); return minDebtCurrent; } /// @notice Queues a transaction to set a new max debt per account /// @dev Requires the policy for keccak(group(creditManager), "MAX_DEBT") to be enabled, /// otherwise auto-fails the check /// @param creditManager Adress of CM to update the limits for /// @param maxDebt The new maximal debt amount function setMaxDebtLimit(address creditManager, uint128 maxDebt) external override { address creditConfigurator = ICreditManagerV3(creditManager).creditConfigurator(); address creditFacade = ICreditManagerV3(creditManager).creditFacade(); uint128 maxDebtCurrent = getMaxDebtLimit(creditFacade); if (!_checkPolicy(creditManager, "MAX_DEBT", uint256(maxDebtCurrent), uint256(maxDebt))) { revert ParameterChecksFailedException(); // U:[CT-4B] } _queueTransaction({ target: creditConfigurator, signature: "setMaxDebtLimit(uint128)", data: abi.encode(maxDebt), delay: _getPolicyDelay(creditManager, "MAX_DEBT"), sanityCheckValue: maxDebtCurrent, sanityCheckCallData: abi.encodeCall(this.getMaxDebtLimit, (creditFacade)) }); // U:[CT-4B] } /// @dev Retrieves the current max debt limit for a Credit Manager function getMaxDebtLimit(address creditFacade) public view returns (uint128) { (, uint128 maxDebtCurrent) = ICreditFacadeV3(creditFacade).debtLimits(); return maxDebtCurrent; } /// @notice Queues a transaction to set a new debt limit for a Credit Manager /// @dev Requires the policy for keccak(group(creditManager), "CREDIT_MANAGER_DEBT_LIMIT") to be enabled, /// otherwise auto-fails the check /// @param creditManager Adress of CM to update the debt limit for /// @param debtLimit The new debt limit function setCreditManagerDebtLimit(address creditManager, uint256 debtLimit) external override { IPoolV3 pool = IPoolV3(ICreditManagerV3(creditManager).pool()); uint256 debtLimitCurrent = getCreditManagerDebtLimit(address(pool), creditManager); if (!_checkPolicy(creditManager, "CREDIT_MANAGER_DEBT_LIMIT", uint256(debtLimitCurrent), uint256(debtLimit))) { revert ParameterChecksFailedException(); // U:[CT-5] } _queueTransaction({ target: address(pool), signature: "setCreditManagerDebtLimit(address,uint256)", data: abi.encode(address(creditManager), debtLimit), delay: _getPolicyDelay(creditManager, "CREDIT_MANAGER_DEBT_LIMIT"), sanityCheckValue: debtLimitCurrent, sanityCheckCallData: abi.encodeCall(this.getCreditManagerDebtLimit, (address(pool), creditManager)) }); // U:[CT-5] } /// @dev Retrieves the current total debt limit for Credit Manager from its pool function getCreditManagerDebtLimit(address pool, address creditManager) public view returns (uint256) { return IPoolV3(pool).creditManagerDebtLimit(creditManager); } /// @notice Queues a transaction to start a liquidation threshold ramp /// @dev Requires the policy for keccak(group(creditManager), group(token), "TOKEN_LT") to be enabled, /// otherwise auto-fails the check /// @param creditManager Adress of CM to update the LT for /// @param token Token to ramp the LT for /// @param liquidationThresholdFinal The liquidation threshold value after the ramp /// @param rampDuration Duration of the ramp function rampLiquidationThreshold( address creditManager, address token, uint16 liquidationThresholdFinal, uint40 rampStart, uint24 rampDuration ) external override { bytes32 policyHash = keccak256(abi.encode(_group[creditManager], _group[token], "TOKEN_LT")); uint256 ltCurrent = ICreditManagerV3(creditManager).liquidationThresholds(token); uint256 delay = _getPolicyDelay(policyHash); if ( !_checkPolicy(policyHash, uint256(ltCurrent), uint256(liquidationThresholdFinal)) || rampDuration < MIN_LT_RAMP_DURATION || rampStart < block.timestamp + delay ) { revert ParameterChecksFailedException(); // U: [CT-6] } _queueTransaction({ target: ICreditManagerV3(creditManager).creditConfigurator(), signature: "rampLiquidationThreshold(address,uint16,uint40,uint24)", data: abi.encode(token, liquidationThresholdFinal, rampStart, rampDuration), delay: delay, sanityCheckValue: uint256(getLTRampParamsHash(creditManager, token)), sanityCheckCallData: abi.encodeCall(this.getLTRampParamsHash, (creditManager, token)) }); // U: [CT-6] } /// @dev Retrives the keccak of liquidation threshold params for a token function getLTRampParamsHash(address creditManager, address token) public view returns (bytes32) { (uint16 ltInitial, uint16 ltFinal, uint40 timestampRampStart, uint24 rampDuration) = ICreditManagerV3(creditManager).ltParams(token); return keccak256(abi.encode(ltInitial, ltFinal, timestampRampStart, rampDuration)); } /// @notice Queues a transaction to forbid a third party contract adapter /// @dev Requires the policy for keccak(group(creditManager), "FORBID_ADAPTER") to be enabled, /// otherwise auto-fails the check /// @param creditManager Adress of CM to forbid an adapter for /// @param adapter Address of adapter to forbid function forbidAdapter(address creditManager, address adapter) external override { bytes32 policyHash = keccak256(abi.encode(_group[creditManager], "FORBID_ADAPTER")); address creditConfigurator = ICreditManagerV3(creditManager).creditConfigurator(); // For `forbidAdapter`, there is no value to modify // A policy check simply verifies that this controller has access to the function in a given group if (!_checkPolicy(policyHash, 0, 0)) { revert ParameterChecksFailedException(); // U: [CT-10] } _queueTransaction({ target: creditConfigurator, signature: "forbidAdapter(address)", data: abi.encode(adapter), delay: _getPolicyDelay(policyHash), sanityCheckValue: 0, sanityCheckCallData: "" }); // U: [CT-10] } /// @notice Queues a transaction to set a new limit on quotas for particular pool and token /// @dev Requires the policy for keccak(group(pool), group(token), "TOKEN_LIMIT") to be enabled, /// otherwise auto-fails the check /// @param pool Pool to update the limit for /// @param token Token to update the limit for /// @param limit The new value of the limit function setTokenLimit(address pool, address token, uint96 limit) external override { bytes32 policyHash = keccak256(abi.encode(_group[pool], _group[token], "TOKEN_LIMIT")); address poolQuotaKeeper = IPoolV3(pool).poolQuotaKeeper(); uint96 oldLimit = getTokenLimit(poolQuotaKeeper, token); if (!_checkPolicy(policyHash, uint256(oldLimit), uint256(limit))) { revert ParameterChecksFailedException(); // U: [CT-11] } _queueTransaction({ target: poolQuotaKeeper, signature: "setTokenLimit(address,uint96)", data: abi.encode(token, limit), delay: _getPolicyDelay(policyHash), sanityCheckValue: oldLimit, sanityCheckCallData: abi.encodeCall(this.getTokenLimit, (poolQuotaKeeper, token)) }); // U: [CT-11] } /// @dev Retrieves the per-token quota limit from pool quota keeper function getTokenLimit(address poolQuotaKeeper, address token) public view returns (uint96) { (,,,, uint96 oldLimit,) = IPoolQuotaKeeperV3(poolQuotaKeeper).getTokenQuotaParams(token); return oldLimit; } /// @notice Queues a transaction to set a new quota increase (trading) fee for a particular pool and token /// @dev Requires the policy for keccak(group(pool), group(token), "TOKEN_QUOTA_INCREASE_FEE") to be enabled, /// otherwise auto-fails the check /// @param pool Pool to update the limit for /// @param token Token to update the limit for /// @param quotaIncreaseFee The new value of the fee in bp function setTokenQuotaIncreaseFee(address pool, address token, uint16 quotaIncreaseFee) external override { bytes32 policyHash = keccak256(abi.encode(_group[pool], _group[token], "TOKEN_QUOTA_INCREASE_FEE")); address poolQuotaKeeper = IPoolV3(pool).poolQuotaKeeper(); uint16 quotaIncreaseFeeOld = getTokenQuotaIncreaseFee(poolQuotaKeeper, token); if (!_checkPolicy(policyHash, uint256(quotaIncreaseFeeOld), uint256(quotaIncreaseFee))) { revert ParameterChecksFailedException(); // U: [CT-12] } _queueTransaction({ target: poolQuotaKeeper, signature: "setTokenQuotaIncreaseFee(address,uint16)", data: abi.encode(token, quotaIncreaseFee), delay: _getPolicyDelay(policyHash), sanityCheckValue: quotaIncreaseFeeOld, sanityCheckCallData: abi.encodeCall(this.getTokenQuotaIncreaseFee, (poolQuotaKeeper, token)) }); // U: [CT-12] } /// @dev Retrieves the quota increase fee for a token function getTokenQuotaIncreaseFee(address poolQuotaKeeper, address token) public view returns (uint16) { (,, uint16 quotaIncreaseFeeOld,,,) = IPoolQuotaKeeperV3(poolQuotaKeeper).getTokenQuotaParams(token); return quotaIncreaseFeeOld; } /// @notice Queues a transaction to set a new total debt limit for the entire pool /// @dev Requires the policy for keccak(group(pool), "TOTAL_DEBT_LIMIT") to be enabled, /// otherwise auto-fails the check /// @param pool Pool to update the limit for /// @param newLimit The new value of the limit function setTotalDebtLimit(address pool, uint256 newLimit) external override { bytes32 policyHash = keccak256(abi.encode(_group[pool], "TOTAL_DEBT_LIMIT")); uint256 totalDebtLimitOld = getTotalDebtLimit(pool); if (!_checkPolicy(policyHash, uint256(totalDebtLimitOld), uint256(newLimit))) { revert ParameterChecksFailedException(); // U: [CT-13] } _queueTransaction({ target: pool, signature: "setTotalDebtLimit(uint256)", data: abi.encode(newLimit), delay: _getPolicyDelay(policyHash), sanityCheckValue: totalDebtLimitOld, sanityCheckCallData: abi.encodeCall(this.getTotalDebtLimit, (pool)) }); // U: [CT-13] } /// @dev Retrieves the total debt limit for a pool function getTotalDebtLimit(address pool) public view returns (uint256) { return IPoolV3(pool).totalDebtLimit(); } /// @notice Queues a transaction to set a new withdrawal fee in a pool /// @dev Requires the policy for keccak(group(pool), "WITHDRAW_FEE") to be enabled, /// otherwise auto-fails the check /// @param pool Pool to update the limit for /// @param newFee The new value of the fee in bp function setWithdrawFee(address pool, uint256 newFee) external override { bytes32 policyHash = keccak256(abi.encode(_group[pool], "WITHDRAW_FEE")); uint256 withdrawFeeOld = IPoolV3(pool).withdrawFee(); if (!_checkPolicy(policyHash, withdrawFeeOld, newFee)) { revert ParameterChecksFailedException(); // U: [CT-14] } _queueTransaction({ target: pool, signature: "setWithdrawFee(uint256)", data: abi.encode(newFee), delay: _getPolicyDelay(policyHash), sanityCheckValue: withdrawFeeOld, sanityCheckCallData: abi.encodeCall(this.getWithdrawFee, (pool)) }); // U: [CT-14] } /// @dev Retrieves the withdrawal fee for a pool function getWithdrawFee(address pool) public view returns (uint256) { return IPoolV3(pool).withdrawFee(); } /// @notice Queues a transaction to set a new minimal quota interest rate for particular pool and token /// @dev Requires the policy for keccak(group(pool), group(token), "TOKEN_QUOTA_MIN_RATE") to be enabled, /// otherwise auto-fails the check /// @param pool Pool to update the limit for /// @param token Token to set the new fee for /// @param rate The new minimal rate function setMinQuotaRate(address pool, address token, uint16 rate) external override { bytes32 policyHash = keccak256(abi.encode(_group[pool], _group[token], "TOKEN_QUOTA_MIN_RATE")); address poolQuotaKeeper = IPoolV3(pool).poolQuotaKeeper(); address gauge = IPoolQuotaKeeperV3(poolQuotaKeeper).gauge(); uint16 minRateCurrent = getMinQuotaRate(gauge, token); if (!_checkPolicy(policyHash, uint256(minRateCurrent), uint256(rate))) { revert ParameterChecksFailedException(); // U: [CT-15A] } _queueTransaction({ target: gauge, signature: "changeQuotaMinRate(address,uint16)", data: abi.encode(token, rate), delay: _getPolicyDelay(policyHash), sanityCheckValue: minRateCurrent, sanityCheckCallData: abi.encodeCall(this.getMinQuotaRate, (gauge, token)) }); // U: [CT-15A] } /// @dev Retrieves the current minimal quota rate for a token in a gauge function getMinQuotaRate(address gauge, address token) public view returns (uint16) { (uint16 minRateCurrent,,,) = IGaugeV3(gauge).quotaRateParams(token); return minRateCurrent; } /// @notice Queues a transaction to set a new maximal quota interest rate for particular pool and token /// @dev Requires the policy for keccak(group(pool), group(token), "TOKEN_QUOTA_MAX_RATE") to be enabled, /// otherwise auto-fails the check /// @param pool Pool to update the limit for /// @param token Token to set the new fee for /// @param rate The new maximal rate function setMaxQuotaRate(address pool, address token, uint16 rate) external override { bytes32 policyHash = keccak256(abi.encode(_group[pool], _group[token], "TOKEN_QUOTA_MAX_RATE")); address poolQuotaKeeper = IPoolV3(pool).poolQuotaKeeper(); address gauge = IPoolQuotaKeeperV3(poolQuotaKeeper).gauge(); uint16 maxRateCurrent = getMaxQuotaRate(gauge, token); if (!_checkPolicy(policyHash, uint256(maxRateCurrent), uint256(rate))) { revert ParameterChecksFailedException(); // U: [CT-15B] } _queueTransaction({ target: gauge, signature: "changeQuotaMaxRate(address,uint16)", data: abi.encode(token, rate), delay: _getPolicyDelay(policyHash), sanityCheckValue: maxRateCurrent, sanityCheckCallData: abi.encodeCall(this.getMaxQuotaRate, (gauge, token)) }); // U: [CT-15B] } /// @dev Retrieves the current maximal quota rate for a token in a gauge function getMaxQuotaRate(address gauge, address token) public view returns (uint16) { (, uint16 maxRateCurrent,,) = IGaugeV3(gauge).quotaRateParams(token); return maxRateCurrent; } /// @notice Queues a transaction to activate or deactivate reserve price feed for a token in price oracle /// @dev Requires the policy for keccak(group(priceOracle), group(token), "RESERVE_PRICE_FEED_STATUS") /// to be enabled, otherwise auto-fails the check /// @param priceOracle Price oracle to change reserve price feed status for /// @param token Token to change reserve price feed status for /// @param active New reserve price feed status (`true` to activate, `false` to deactivate) function setReservePriceFeedStatus(address priceOracle, address token, bool active) external override { bytes32 policyHash = keccak256(abi.encode(_group[priceOracle], _group[token], "RESERVE_PRICE_FEED_STATUS")); if (!_checkPolicy(policyHash, 0, 0)) { revert ParameterChecksFailedException(); // U:[CT-16] } _queueTransaction({ target: priceOracle, signature: "setReservePriceFeedStatus(address,bool)", data: abi.encode(token, active), delay: _getPolicyDelay(policyHash), sanityCheckValue: 0, sanityCheckCallData: "" }); // U:[CT-16] } /// @notice Queues a transaction to forbid permissionless bounds update in an LP price feed /// @dev Requires the policy for keccak(group(priceFeed), "UPDATE_BOUNDS_ALLOWED") to be enabled, /// otherwise auto-fails the check /// @param priceFeed The price feed to forbid bounds update for function forbidBoundsUpdate(address priceFeed) external override { if (!_checkPolicy(priceFeed, "UPDATE_BOUNDS_ALLOWED", 0, 0)) { revert ParameterChecksFailedException(); // U:[CT-17] } _queueTransaction({ target: priceFeed, signature: "forbidBoundsUpdate()", data: "", delay: _getPolicyDelay(priceFeed, "UPDATE_BOUNDS_ALLOWED"), sanityCheckValue: 0, sanityCheckCallData: "" }); // U:[CT-17] } /// @dev Internal function that stores the transaction in the queued tx map /// @param target The contract to call /// @param signature The signature of the called function /// @param data The call data /// @return Hash of the queued transaction function _queueTransaction( address target, string memory signature, bytes memory data, uint256 delay, uint256 sanityCheckValue, bytes memory sanityCheckCallData ) internal returns (bytes32) { uint256 eta = block.timestamp + delay; bytes32 txHash = keccak256(abi.encode(msg.sender, target, signature, data, eta)); queuedTransactions[txHash] = QueuedTransactionData({ queued: true, executor: msg.sender, target: target, eta: uint40(eta), signature: signature, data: data, sanityCheckValue: sanityCheckValue, sanityCheckCallData: sanityCheckCallData }); emit QueueTransaction({ txHash: txHash, executor: msg.sender, target: target, signature: signature, data: data, eta: uint40(eta) }); return txHash; } // --------- // // EXECUTION // // --------- // /// @notice Sets the transaction's queued status as false, effectively cancelling it /// @param txHash Hash of the transaction to be cancelled function cancelTransaction(bytes32 txHash) external override vetoAdminOnly // U: [CT-7] { queuedTransactions[txHash].queued = false; emit CancelTransaction(txHash); } /// @notice Executes a queued transaction /// @param txHash Hash of the transaction to be executed function executeTransaction(bytes32 txHash) external override { QueuedTransactionData memory qtd = queuedTransactions[txHash]; if (!qtd.queued) { revert TxNotQueuedException(); // U: [CT-7] } if (msg.sender != qtd.executor) { revert CallerNotExecutorException(); // U: [CT-9] } address target = qtd.target; uint40 eta = qtd.eta; string memory signature = qtd.signature; bytes memory data = qtd.data; if (block.timestamp < eta || block.timestamp > eta + GRACE_PERIOD) { revert TxExecutedOutsideTimeWindowException(); // U: [CT-9] } // In order to ensure that we do not accidentally override a change // made by configurator or another admin, the current value of the parameter // is compared to the value at the moment of tx being queued if (qtd.sanityCheckCallData.length != 0) { (, bytes memory returndata) = address(this).staticcall(qtd.sanityCheckCallData); if (abi.decode(returndata, (uint256)) != qtd.sanityCheckValue) { revert ParameterChangedAfterQueuedTxException(); } } queuedTransactions[txHash].queued = false; bytes memory callData; if (bytes(signature).length == 0) { callData = data; } else { callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); } (bool success,) = target.call(callData); if (!success) { revert TxExecutionRevertedException(); // U: [CT-9] } emit ExecuteTransaction(txHash); // U: [CT-9] } // ------------- // // CONFIGURATION // // ------------- // /// @notice Sets a new veto admin address function setVetoAdmin(address newAdmin) external override configuratorOnly // U: [CT-8] { if (vetoAdmin != newAdmin) { vetoAdmin = newAdmin; // U: [CT-8] emit SetVetoAdmin(newAdmin); // U: [CT-8] } } }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {ACLNonReentrantTrait} from "../traits/ACLNonReentrantTrait.sol"; import {PERCENTAGE_FACTOR} from "@gearbox-protocol/core-v2/contracts/libraries/Constants.sol"; /// @notice Policy that determines checks performed on a parameter /// Each policy is defined for a contract group, which is a string /// identifier for a set of contracts /// @param enabled Determines whether the policy is enabled. A disabled policy will auto-fail the policy check. /// @param admin The admin that can change the parameter under the given policy /// @param delay The delay before the transaction can be triggered under a given policy /// @param flags Bitmask of flags that determine which policy checks to apply on parameter change: /// * 0 - check exact value /// * 1 - check min value /// * 2 - check max value /// * 3 - check min change /// * 4 - check max change /// * 5 - check min pct change /// * 6 - check max pct change /// @param exactValue Exact value to check the incoming parameter value against, if applies /// @param minValue Min value to check the incoming parameter value against, if applies /// @param maxValue Max value to check the incoming parameter value against, if applies /// @param referencePoint A reference value of a parameter to check change magnitudes against; /// When the reference update period has elapsed since the last reference point update, /// the reference point is updated to the 'current' value on the next parameter change /// NB: Should not be changed manually in most cases /// @param referencePointUpdatePeriod The minimal time period after which the RP can be updated /// @param referencePointTimestampLU Last timestamp at which the reference point was updated /// NB: Should not be changed manually in most cases /// @param minPctChangeDown Min percentage decrease for new values, relative to reference point /// @param minPctChangeUp Min percentage increase for new values, relative to reference point /// @param maxPctChangeDown Max percentage decrease for new values, relative to reference point /// @param maxPctChangeUp Max percentage increase for new values, relative to reference point /// @param minChange Min absolute changes for new values, relative to reference point /// @param maxChange Max absolute changes for new values, relative to reference point struct Policy { bool enabled; address admin; uint40 delay; uint8 flags; uint256 exactValue; uint256 minValue; uint256 maxValue; uint256 referencePoint; uint40 referencePointUpdatePeriod; uint40 referencePointTimestampLU; uint16 minPctChangeDown; uint16 minPctChangeUp; uint16 maxPctChangeDown; uint16 maxPctChangeUp; uint256 minChange; uint256 maxChange; } /// @title Policy manager V3 /// @dev A contract for managing bounds and conditions for mission-critical protocol params abstract contract PolicyManagerV3 is ACLNonReentrantTrait { uint256 internal constant CHECK_EXACT_VALUE_FLAG = 1; uint256 internal constant CHECK_MIN_VALUE_FLAG = 1 << 1; uint256 internal constant CHECK_MAX_VALUE_FLAG = 1 << 2; uint256 internal constant CHECK_MIN_CHANGE_FLAG = 1 << 3; uint256 internal constant CHECK_MAX_CHANGE_FLAG = 1 << 4; uint256 internal constant CHECK_MIN_PCT_CHANGE_FLAG = 1 << 5; uint256 internal constant CHECK_MAX_PCT_CHANGE_FLAG = 1 << 6; /// @dev Mapping from parameter hashes to metaparameters mapping(bytes32 => Policy) internal _policies; /// @dev Mapping from a contract address to its group mapping(address => string) internal _group; /// @notice Emitted when new policy is set event SetPolicy(bytes32 indexed policyHash, bool enabled); /// @notice Emitted when new policy group of the address is set event SetGroup(address indexed contractAddress, string indexed group); constructor(address _addressProvider) ACLNonReentrantTrait(_addressProvider) {} /// @notice Sets the params for a new or existing policy, using policy UID as key /// @param policyHash A unique identifier for a policy, generally, should be a hash of (GROUP_NAME, PARAMETER_NAME) /// @param policyParams Policy parameters function setPolicy(bytes32 policyHash, Policy memory policyParams) external configuratorOnly // U:[PM-1] { policyParams.enabled = true; // U:[PM-1] _policies[policyHash] = policyParams; // U:[PM-1] emit SetPolicy({policyHash: policyHash, enabled: true}); // U:[PM-1] } /// @notice Disables the policy which makes all requested checks for the passed policy hash to auto-fail /// @param policyHash A unique identifier for a policy function disablePolicy(bytes32 policyHash) public configuratorOnly // U:[PM-2] { _policies[policyHash].enabled = false; // U:[PM-2] emit SetPolicy({policyHash: policyHash, enabled: false}); // U:[PM-2] } /// @notice Retrieves policy from policy UID function getPolicy(bytes32 policyHash) external view returns (Policy memory) { return _policies[policyHash]; // U:[PM-1] } /// @notice Sets the policy group of the address function setGroup(address contractAddress, string calldata group) external configuratorOnly { _group[contractAddress] = group; // U:[PM-1] emit SetGroup(contractAddress, group); // U:[PM-1] } /// @notice Retrieves the group associated with a contract function getGroup(address contractAddress) external view returns (string memory) { return _group[contractAddress]; // U:[PM-1] } /// @dev Returns policy transaction delay, with policy retrieved based on contract and parameter name function _getPolicyDelay(address contractAddress, string memory paramName) internal view returns (uint256) { bytes32 policyHash = keccak256(abi.encode(_group[contractAddress], paramName)); return _policies[policyHash].delay; } /// @dev Returns policy transaction delay, with policy retrieved based on policy UID function _getPolicyDelay(bytes32 policyHash) internal view returns (uint256) { return _policies[policyHash].delay; } /// @dev Performs parameter checks, with policy retrieved based on contract and parameter name function _checkPolicy(address contractAddress, string memory paramName, uint256 oldValue, uint256 newValue) internal returns (bool) { bytes32 policyHash = keccak256(abi.encode(_group[contractAddress], paramName)); return _checkPolicy(policyHash, oldValue, newValue); } /// @dev Performs parameter checks, with policy retrieved based on policy UID function _checkPolicy(bytes32 policyHash, uint256 oldValue, uint256 newValue) internal returns (bool) { Policy storage policy = _policies[policyHash]; if (!policy.enabled) return false; // U:[PM-2] if (policy.admin != msg.sender) return false; uint8 flags = policy.flags; if (flags & CHECK_EXACT_VALUE_FLAG != 0) { if (newValue != policy.exactValue) return false; // U:[PM-3] } if (flags & CHECK_MIN_VALUE_FLAG != 0) { if (newValue < policy.minValue) return false; // U:[PM-4] } if (flags & CHECK_MAX_VALUE_FLAG != 0) { if (newValue > policy.maxValue) return false; // U:[PM-5] } uint256 referencePoint; // The policy uses a reference point to gauge relative parameter changes. A reference point // is a value that is set to current value on updating a parameter. All future values for a period // will be rubber-banded to the reference point, until the refresh period elapses and it is updated again. if ( flags & (CHECK_MIN_CHANGE_FLAG | CHECK_MAX_CHANGE_FLAG | CHECK_MIN_PCT_CHANGE_FLAG | CHECK_MAX_PCT_CHANGE_FLAG) != 0 ) { if (block.timestamp > policy.referencePointTimestampLU + policy.referencePointUpdatePeriod) { referencePoint = oldValue; policy.referencePoint = referencePoint; // U:[PM-6] policy.referencePointTimestampLU = uint40(block.timestamp); // U:[PM-6] } else { referencePoint = policy.referencePoint; } (uint256 diff, bool isIncrease) = calcDiff(newValue, referencePoint); if (flags & CHECK_MIN_CHANGE_FLAG != 0) { if (diff < policy.minChange) return false; // U:[PM-7] } if (flags & CHECK_MAX_CHANGE_FLAG != 0) { if (diff > policy.maxChange) return false; // U:[PM-8] } if (flags & (CHECK_MIN_PCT_CHANGE_FLAG | CHECK_MAX_PCT_CHANGE_FLAG) != 0) { uint256 pctDiff = diff * PERCENTAGE_FACTOR / referencePoint; if ( flags & CHECK_MIN_PCT_CHANGE_FLAG != 0 && pctDiff < (isIncrease ? policy.minPctChangeUp : policy.minPctChangeDown) ) return false; // U:[PM-9] if ( flags & CHECK_MAX_PCT_CHANGE_FLAG != 0 && pctDiff > (isIncrease ? policy.maxPctChangeUp : policy.maxPctChangeDown) ) return false; // U:[PM-10] } } return true; } /// @dev Returns the absolute difference between two numbers and the flag whether the first one is greater function calcDiff(uint256 a, uint256 b) internal pure returns (uint256, bool) { return a > b ? (a - b, true) : (b - a, false); } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; struct QueuedTransactionData { bool queued; address executor; address target; uint40 eta; string signature; bytes data; uint256 sanityCheckValue; bytes sanityCheckCallData; } interface IControllerTimelockV3Events { /// @notice Emitted when the veto admin of the controller is updated event SetVetoAdmin(address indexed newAdmin); /// @notice Emitted when a transaction is queued event QueueTransaction( bytes32 indexed txHash, address indexed executor, address target, string signature, bytes data, uint40 eta ); /// @notice Emitted when a transaction is executed event ExecuteTransaction(bytes32 indexed txHash); /// @notice Emitted when a transaction is cancelled event CancelTransaction(bytes32 indexed txHash); } /// @title Controller timelock V3 interface interface IControllerTimelockV3 is IControllerTimelockV3Events, IVersion { // -------- // // QUEUEING // // -------- // function setExpirationDate(address creditManager, uint40 expirationDate) external; function setMaxDebtPerBlockMultiplier(address creditManager, uint8 multiplier) external; function setMinDebtLimit(address creditManager, uint128 minDebt) external; function setMaxDebtLimit(address creditManager, uint128 maxDebt) external; function setCreditManagerDebtLimit(address creditManager, uint256 debtLimit) external; function rampLiquidationThreshold( address creditManager, address token, uint16 liquidationThresholdFinal, uint40 rampStart, uint24 rampDuration ) external; function forbidAdapter(address creditManager, address adapter) external; function setTotalDebtLimit(address pool, uint256 newLimit) external; function setTokenLimit(address pool, address token, uint96 limit) external; function setTokenQuotaIncreaseFee(address pool, address token, uint16 quotaIncreaseFee) external; function setMinQuotaRate(address pool, address token, uint16 rate) external; function setMaxQuotaRate(address pool, address token, uint16 rate) external; function setWithdrawFee(address pool, uint256 newFee) external; function setLPPriceFeedLimiter(address priceFeed, uint256 lowerBound) external; function setReservePriceFeedStatus(address priceOracle, address token, bool active) external; function forbidBoundsUpdate(address priceFeed) external; // --------- // // EXECUTION // // --------- // function GRACE_PERIOD() external view returns (uint256); function queuedTransactions(bytes32 txHash) external view returns ( bool queued, address executor, address target, uint40 eta, string memory signature, bytes memory data, uint256 sanityCheckValue, bytes memory sanityCheckCallData ); function executeTransaction(bytes32 txHash) external; function cancelTransaction(bytes32 txHash) external; // ------------- // // CONFIGURATION // // ------------- // function vetoAdmin() external view returns (address); function setVetoAdmin(address newAdmin) external; }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; uint8 constant BOT_PERMISSIONS_SET_FLAG = 1; uint8 constant DEFAULT_MAX_ENABLED_TOKENS = 4; address constant INACTIVE_CREDIT_ACCOUNT_ADDRESS = address(1); /// @notice Debt management type /// - `INCREASE_DEBT` borrows additional funds from the pool, updates account's debt and cumulative interest index /// - `DECREASE_DEBT` repays debt components (quota interest and fees -> base interest and fees -> debt principal) /// and updates all corresponding state varibles (base interest index, quota interest and fees, debt). /// When repaying all the debt, ensures that account has no enabled quotas. enum ManageDebtAction { INCREASE_DEBT, DECREASE_DEBT } /// @notice Collateral/debt calculation mode /// - `GENERIC_PARAMS` returns generic data like account debt and cumulative indexes /// - `DEBT_ONLY` is same as `GENERIC_PARAMS` but includes more detailed debt info, like accrued base/quota /// interest and fees /// - `FULL_COLLATERAL_CHECK_LAZY` checks whether account is sufficiently collateralized in a lazy fashion, /// i.e. it stops iterating over collateral tokens once TWV reaches the desired target. /// Since it may return underestimated TWV, it's only available for internal use. /// - `DEBT_COLLATERAL` is same as `DEBT_ONLY` but also returns total value and total LT-weighted value of /// account's tokens, this mode is used during account liquidation /// - `DEBT_COLLATERAL_SAFE_PRICES` is same as `DEBT_COLLATERAL` but uses safe prices from price oracle enum CollateralCalcTask { GENERIC_PARAMS, DEBT_ONLY, FULL_COLLATERAL_CHECK_LAZY, DEBT_COLLATERAL, DEBT_COLLATERAL_SAFE_PRICES } struct CreditAccountInfo { uint256 debt; uint256 cumulativeIndexLastUpdate; uint128 cumulativeQuotaInterest; uint128 quotaFees; uint256 enabledTokensMask; uint16 flags; uint64 lastDebtUpdate; address borrower; } struct CollateralDebtData { uint256 debt; uint256 cumulativeIndexNow; uint256 cumulativeIndexLastUpdate; uint128 cumulativeQuotaInterest; uint256 accruedInterest; uint256 accruedFees; uint256 totalDebtUSD; uint256 totalValue; uint256 totalValueUSD; uint256 twvUSD; uint256 enabledTokensMask; uint256 quotedTokensMask; address[] quotedTokens; address _poolQuotaKeeper; } struct CollateralTokenData { address token; uint16 ltInitial; uint16 ltFinal; uint40 timestampRampStart; uint24 rampDuration; } struct RevocationPair { address spender; address token; } interface ICreditManagerV3Events { /// @notice Emitted when new credit configurator is set event SetCreditConfigurator(address indexed newConfigurator); } /// @title Credit manager V3 interface interface ICreditManagerV3 is IVersion, ICreditManagerV3Events { function pool() external view returns (address); function underlying() external view returns (address); function creditFacade() external view returns (address); function creditConfigurator() external view returns (address); function addressProvider() external view returns (address); function accountFactory() external view returns (address); function name() external view returns (string memory); // ------------------ // // ACCOUNT MANAGEMENT // // ------------------ // function openCreditAccount(address onBehalfOf) external returns (address); function closeCreditAccount(address creditAccount) external; function liquidateCreditAccount( address creditAccount, CollateralDebtData calldata collateralDebtData, address to, bool isExpired ) external returns (uint256 remainingFunds, uint256 loss); function manageDebt(address creditAccount, uint256 amount, uint256 enabledTokensMask, ManageDebtAction action) external returns (uint256 newDebt, uint256 tokensToEnable, uint256 tokensToDisable); function addCollateral(address payer, address creditAccount, address token, uint256 amount) external returns (uint256 tokensToEnable); function withdrawCollateral(address creditAccount, address token, uint256 amount, address to) external returns (uint256 tokensToDisable); function externalCall(address creditAccount, address target, bytes calldata callData) external returns (bytes memory result); function approveToken(address creditAccount, address token, address spender, uint256 amount) external; function revokeAdapterAllowances(address creditAccount, RevocationPair[] calldata revocations) external; // -------- // // ADAPTERS // // -------- // function adapterToContract(address adapter) external view returns (address targetContract); function contractToAdapter(address targetContract) external view returns (address adapter); function execute(bytes calldata data) external returns (bytes memory result); function approveCreditAccount(address token, uint256 amount) external; function setActiveCreditAccount(address creditAccount) external; function getActiveCreditAccountOrRevert() external view returns (address creditAccount); // ----------------- // // COLLATERAL CHECKS // // ----------------- // function priceOracle() external view returns (address); function fullCollateralCheck( address creditAccount, uint256 enabledTokensMask, uint256[] calldata collateralHints, uint16 minHealthFactor, bool useSafePrices ) external returns (uint256 enabledTokensMaskAfter); function isLiquidatable(address creditAccount, uint16 minHealthFactor) external view returns (bool); function calcDebtAndCollateral(address creditAccount, CollateralCalcTask task) external view returns (CollateralDebtData memory cdd); // ------ // // QUOTAS // // ------ // function poolQuotaKeeper() external view returns (address); function quotedTokensMask() external view returns (uint256); function updateQuota(address creditAccount, address token, int96 quotaChange, uint96 minQuota, uint96 maxQuota) external returns (uint256 tokensToEnable, uint256 tokensToDisable); // --------------------- // // CREDIT MANAGER PARAMS // // --------------------- // function maxEnabledTokens() external view returns (uint8); function fees() external view returns ( uint16 feeInterest, uint16 feeLiquidation, uint16 liquidationDiscount, uint16 feeLiquidationExpired, uint16 liquidationDiscountExpired ); function collateralTokensCount() external view returns (uint8); function getTokenMaskOrRevert(address token) external view returns (uint256 tokenMask); function getTokenByMask(uint256 tokenMask) external view returns (address token); function liquidationThresholds(address token) external view returns (uint16 lt); function ltParams(address token) external view returns (uint16 ltInitial, uint16 ltFinal, uint40 timestampRampStart, uint24 rampDuration); function collateralTokenByMask(uint256 tokenMask) external view returns (address token, uint16 liquidationThreshold); // ------------ // // ACCOUNT INFO // // ------------ // function creditAccountInfo(address creditAccount) external view returns ( uint256 debt, uint256 cumulativeIndexLastUpdate, uint128 cumulativeQuotaInterest, uint128 quotaFees, uint256 enabledTokensMask, uint16 flags, uint64 lastDebtUpdate, address borrower ); function getBorrowerOrRevert(address creditAccount) external view returns (address borrower); function flagsOf(address creditAccount) external view returns (uint16); function setFlagFor(address creditAccount, uint16 flag, bool value) external; function enabledTokensMaskOf(address creditAccount) external view returns (uint256); function creditAccounts() external view returns (address[] memory); function creditAccounts(uint256 offset, uint256 limit) external view returns (address[] memory); function creditAccountsLen() external view returns (uint256); // ------------- // // CONFIGURATION // // ------------- // function addToken(address token) external; function setCollateralTokenData( address token, uint16 ltInitial, uint16 ltFinal, uint40 timestampRampStart, uint24 rampDuration ) external; function setFees( uint16 feeInterest, uint16 feeLiquidation, uint16 liquidationDiscount, uint16 feeLiquidationExpired, uint16 liquidationDiscountExpired ) external; function setQuotedMask(uint256 quotedTokensMask) external; function setMaxEnabledTokens(uint8 maxEnabledTokens) external; function setContractAllowance(address adapter, address targetContract) external; function setCreditFacade(address creditFacade) external; function setPriceOracle(address priceOracle) external; function setCreditConfigurator(address creditConfigurator) external; }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {MultiCall} from "@gearbox-protocol/core-v2/contracts/libraries/MultiCall.sol"; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; import "./ICreditFacadeV3Multicall.sol"; import {AllowanceAction} from "../interfaces/ICreditConfiguratorV3.sol"; /// @notice Debt limits packed into a single slot /// @param minDebt Minimum debt amount per credit account /// @param maxDebt Maximum debt amount per credit account struct DebtLimits { uint128 minDebt; uint128 maxDebt; } /// @notice Info on bad debt liquidation losses packed into a single slot /// @param currentCumulativeLoss Current cumulative loss from bad debt liquidations /// @param maxCumulativeLoss Max cumulative loss incurred before the facade gets paused struct CumulativeLossParams { uint128 currentCumulativeLoss; uint128 maxCumulativeLoss; } /// @notice Collateral check params /// @param collateralHints Optional array of token masks to check first to reduce the amount of computation /// when known subset of account's collateral tokens covers all the debt /// @param minHealthFactor Min account's health factor in bps in order not to revert /// @param enabledTokensMaskAfter Bitmask of account's enabled collateral tokens after the multicall /// @param revertOnForbiddenTokens Whether to revert on enabled forbidden tokens after the multicall /// @param useSafePrices Whether to use safe pricing (min of main and reserve feeds) when evaluating collateral struct FullCheckParams { uint256[] collateralHints; uint16 minHealthFactor; uint256 enabledTokensMaskAfter; bool revertOnForbiddenTokens; bool useSafePrices; } interface ICreditFacadeV3Events { /// @notice Emitted when a new credit account is opened event OpenCreditAccount( address indexed creditAccount, address indexed onBehalfOf, address indexed caller, uint256 referralCode ); /// @notice Emitted when account is closed event CloseCreditAccount(address indexed creditAccount, address indexed borrower); /// @notice Emitted when account is liquidated event LiquidateCreditAccount( address indexed creditAccount, address indexed liquidator, address to, uint256 remainingFunds ); /// @notice Emitted when account's debt is increased event IncreaseDebt(address indexed creditAccount, uint256 amount); /// @notice Emitted when account's debt is decreased event DecreaseDebt(address indexed creditAccount, uint256 amount); /// @notice Emitted when collateral is added to account event AddCollateral(address indexed creditAccount, address indexed token, uint256 amount); /// @notice Emitted when collateral is withdrawn from account event WithdrawCollateral(address indexed creditAccount, address indexed token, uint256 amount, address to); /// @notice Emitted when a multicall is started event StartMultiCall(address indexed creditAccount, address indexed caller); /// @notice Emitted when a call from account to an external contract is made during a multicall event Execute(address indexed creditAccount, address indexed targetContract); /// @notice Emitted when a multicall is finished event FinishMultiCall(); } /// @title Credit facade V3 interface interface ICreditFacadeV3 is IVersion, ICreditFacadeV3Events { function creditManager() external view returns (address); function degenNFT() external view returns (address); function weth() external view returns (address); function botList() external view returns (address); function maxDebtPerBlockMultiplier() external view returns (uint8); function maxQuotaMultiplier() external view returns (uint256); function expirable() external view returns (bool); function expirationDate() external view returns (uint40); function debtLimits() external view returns (uint128 minDebt, uint128 maxDebt); function lossParams() external view returns (uint128 currentCumulativeLoss, uint128 maxCumulativeLoss); function forbiddenTokenMask() external view returns (uint256); function canLiquidateWhilePaused(address) external view returns (bool); // ------------------ // // ACCOUNT MANAGEMENT // // ------------------ // function openCreditAccount(address onBehalfOf, MultiCall[] calldata calls, uint256 referralCode) external payable returns (address creditAccount); function closeCreditAccount(address creditAccount, MultiCall[] calldata calls) external payable; function liquidateCreditAccount(address creditAccount, address to, MultiCall[] calldata calls) external; function multicall(address creditAccount, MultiCall[] calldata calls) external payable; function botMulticall(address creditAccount, MultiCall[] calldata calls) external; function setBotPermissions(address creditAccount, address bot, uint192 permissions) external; // ------------- // // CONFIGURATION // // ------------- // function setExpirationDate(uint40 newExpirationDate) external; function setDebtLimits(uint128 newMinDebt, uint128 newMaxDebt, uint8 newMaxDebtPerBlockMultiplier) external; function setBotList(address newBotList) external; function setCumulativeLossParams(uint128 newMaxCumulativeLoss, bool resetCumulativeLoss) external; function setTokenAllowance(address token, AllowanceAction allowance) external; function setEmergencyLiquidator(address liquidator, AllowanceAction allowance) external; }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; pragma abicoder v1; import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol"; import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; interface IPoolV3Events { /// @notice Emitted when depositing liquidity with referral code event Refer(address indexed onBehalfOf, uint256 indexed referralCode, uint256 amount); /// @notice Emitted when credit account borrows funds from the pool event Borrow(address indexed creditManager, address indexed creditAccount, uint256 amount); /// @notice Emitted when credit account's debt is repaid to the pool event Repay(address indexed creditManager, uint256 borrowedAmount, uint256 profit, uint256 loss); /// @notice Emitted when incurred loss can't be fully covered by burning treasury's shares event IncurUncoveredLoss(address indexed creditManager, uint256 loss); /// @notice Emitted when new interest rate model contract is set event SetInterestRateModel(address indexed newInterestRateModel); /// @notice Emitted when new pool quota keeper contract is set event SetPoolQuotaKeeper(address indexed newPoolQuotaKeeper); /// @notice Emitted when new total debt limit is set event SetTotalDebtLimit(uint256 limit); /// @notice Emitted when new credit manager is connected to the pool event AddCreditManager(address indexed creditManager); /// @notice Emitted when new debt limit is set for a credit manager event SetCreditManagerDebtLimit(address indexed creditManager, uint256 newLimit); /// @notice Emitted when new withdrawal fee is set event SetWithdrawFee(uint256 fee); } /// @title Pool V3 interface interface IPoolV3 is IVersion, IPoolV3Events, IERC4626, IERC20Permit { function addressProvider() external view returns (address); function underlyingToken() external view returns (address); function treasury() external view returns (address); function withdrawFee() external view returns (uint16); function creditManagers() external view returns (address[] memory); function availableLiquidity() external view returns (uint256); function expectedLiquidity() external view returns (uint256); function expectedLiquidityLU() external view returns (uint256); // ---------------- // // ERC-4626 LENDING // // ---------------- // function depositWithReferral(uint256 assets, address receiver, uint256 referralCode) external returns (uint256 shares); function mintWithReferral(uint256 shares, address receiver, uint256 referralCode) external returns (uint256 assets); // --------- // // BORROWING // // --------- // function totalBorrowed() external view returns (uint256); function totalDebtLimit() external view returns (uint256); function creditManagerBorrowed(address creditManager) external view returns (uint256); function creditManagerDebtLimit(address creditManager) external view returns (uint256); function creditManagerBorrowable(address creditManager) external view returns (uint256 borrowable); function lendCreditAccount(uint256 borrowedAmount, address creditAccount) external; function repayCreditAccount(uint256 repaidAmount, uint256 profit, uint256 loss) external; // ------------- // // INTEREST RATE // // ------------- // function interestRateModel() external view returns (address); function baseInterestRate() external view returns (uint256); function supplyRate() external view returns (uint256); function baseInterestIndex() external view returns (uint256); function baseInterestIndexLU() external view returns (uint256); function lastBaseInterestUpdate() external view returns (uint40); // ------ // // QUOTAS // // ------ // function poolQuotaKeeper() external view returns (address); function quotaRevenue() external view returns (uint256); function lastQuotaRevenueUpdate() external view returns (uint40); function updateQuotaRevenue(int256 quotaRevenueDelta) external; function setQuotaRevenue(uint256 newQuotaRevenue) external; // ------------- // // CONFIGURATION // // ------------- // function setInterestRateModel(address newInterestRateModel) external; function setPoolQuotaKeeper(address newPoolQuotaKeeper) external; function setTotalDebtLimit(uint256 newLimit) external; function setCreditManagerDebtLimit(address creditManager, uint256 newLimit) external; function setWithdrawFee(uint256 newWithdrawFee) external; }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; struct TokenQuotaParams { uint16 rate; uint192 cumulativeIndexLU; uint16 quotaIncreaseFee; uint96 totalQuoted; uint96 limit; } struct AccountQuota { uint96 quota; uint192 cumulativeIndexLU; } interface IPoolQuotaKeeperV3Events { /// @notice Emitted when account's quota for a token is updated event UpdateQuota(address indexed creditAccount, address indexed token, int96 quotaChange); /// @notice Emitted when token's quota rate is updated event UpdateTokenQuotaRate(address indexed token, uint16 rate); /// @notice Emitted when the gauge is updated event SetGauge(address indexed newGauge); /// @notice Emitted when a new credit manager is allowed event AddCreditManager(address indexed creditManager); /// @notice Emitted when a new token is added as quoted event AddQuotaToken(address indexed token); /// @notice Emitted when a new total quota limit is set for a token event SetTokenLimit(address indexed token, uint96 limit); /// @notice Emitted when a new one-time quota increase fee is set for a token event SetQuotaIncreaseFee(address indexed token, uint16 fee); } /// @title Pool quota keeper V3 interface interface IPoolQuotaKeeperV3 is IPoolQuotaKeeperV3Events, IVersion { function pool() external view returns (address); function underlying() external view returns (address); // ----------------- // // QUOTAS MANAGEMENT // // ----------------- // function updateQuota(address creditAccount, address token, int96 requestedChange, uint96 minQuota, uint96 maxQuota) external returns (uint128 caQuotaInterestChange, uint128 fees, bool enableToken, bool disableToken); function removeQuotas(address creditAccount, address[] calldata tokens, bool setLimitsToZero) external; function accrueQuotaInterest(address creditAccount, address[] calldata tokens) external; function getQuotaRate(address) external view returns (uint16); function cumulativeIndex(address token) external view returns (uint192); function isQuotedToken(address token) external view returns (bool); function getQuota(address creditAccount, address token) external view returns (uint96 quota, uint192 cumulativeIndexLU); function getTokenQuotaParams(address token) external view returns ( uint16 rate, uint192 cumulativeIndexLU, uint16 quotaIncreaseFee, uint96 totalQuoted, uint96 limit, bool isActive ); function getQuotaAndOutstandingInterest(address creditAccount, address token) external view returns (uint96 quoted, uint128 outstandingInterest); function poolQuotaRevenue() external view returns (uint256); function lastQuotaRateUpdate() external view returns (uint40); // ------------- // // CONFIGURATION // // ------------- // function gauge() external view returns (address); function setGauge(address _gauge) external; function creditManagers() external view returns (address[] memory); function addCreditManager(address _creditManager) external; function quotedTokens() external view returns (address[] memory); function addQuotaToken(address token) external; function updateRates() external; function setTokenLimit(address token, uint96 limit) external; function setTokenQuotaIncreaseFee(address token, uint16 fee) external; }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; import {IVotingContractV3} from "./IVotingContractV3.sol"; struct QuotaRateParams { uint16 minRate; uint16 maxRate; uint96 totalVotesLpSide; uint96 totalVotesCaSide; } struct UserVotes { uint96 votesLpSide; uint96 votesCaSide; } interface IGaugeV3Events { /// @notice Emitted when epoch is updated event UpdateEpoch(uint16 epochNow); /// @notice Emitted when a user submits a vote event Vote(address indexed user, address indexed token, uint96 votes, bool lpSide); /// @notice Emitted when a user removes a vote event Unvote(address indexed user, address indexed token, uint96 votes, bool lpSide); /// @notice Emitted when a new quota token is added in the PoolQuotaKeeper event AddQuotaToken(address indexed token, uint16 minRate, uint16 maxRate); /// @notice Emitted when quota interest rate parameters are changed event SetQuotaTokenParams(address indexed token, uint16 minRate, uint16 maxRate); /// @notice Emitted when the frozen epoch status changes event SetFrozenEpoch(bool status); } /// @title Gauge V3 interface interface IGaugeV3 is IGaugeV3Events, IVotingContractV3, IVersion { function pool() external view returns (address); function voter() external view returns (address); function updateEpoch() external; function epochLastUpdate() external view returns (uint16); function getRates(address[] calldata tokens) external view returns (uint16[] memory rates); function userTokenVotes(address user, address token) external view returns (uint96 votesLpSide, uint96 votesCaSide); function quotaRateParams(address token) external view returns (uint16 minRate, uint16 maxRate, uint96 totalVotesLpSide, uint96 totalVotesCaSide); // ------------- // // CONFIGURATION // // ------------- // function epochFrozen() external view returns (bool); function setFrozenEpoch(bool status) external; function isTokenAdded(address token) external view returns (bool); function addQuotaToken(address token, uint16 minRate, uint16 maxRate) external; function changeQuotaMinRate(address token, uint16 minRate) external; function changeQuotaMaxRate(address token, uint16 maxRate) external; }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; interface ILPPriceFeedV2Events { /// @dev Emits on updating the virtual price bounds event NewLimiterParams(uint256 lowerBound, uint256 upperBound); } interface ILPPriceFeedV2Exceptions { /// @dev Thrown on returning a value that violates the current bounds error ValueOutOfRangeException(); /// @dev Thrown on failing sanity checks when setting new bounds error IncorrectLimitsException(); } /// @title Interface for LP PriceFeeds with limiter interface ILPPriceFeedV2 is AggregatorV3Interface, ILPPriceFeedV2Events, ILPPriceFeedV2Exceptions { /// @dev Sets the lower and upper bounds for virtual price. /// @param _lowerBound The new lower bound /// @notice The upper bound is computed automatically function setLimiter(uint256 _lowerBound) external; /// @dev Returns the lower bound function lowerBound() external view returns (uint256); /// @dev Returns the upper bound function upperBound() external view returns (uint256); /// @dev Returns the pre-defined window between the lower and upper bounds /// @notice In bp format function delta() external view returns (uint256); }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; // ------- // // GENERAL // // ------- // /// @notice Thrown on attempting to set an important address to zero address error ZeroAddressException(); /// @notice Thrown when attempting to pass a zero amount to a funding-related operation error AmountCantBeZeroException(); /// @notice Thrown on incorrect input parameter error IncorrectParameterException(); /// @notice Thrown when balance is insufficient to perform an operation error InsufficientBalanceException(); /// @notice Thrown if parameter is out of range error ValueOutOfRangeException(); /// @notice Thrown when trying to send ETH to a contract that is not allowed to receive ETH directly error ReceiveIsNotAllowedException(); /// @notice Thrown on attempting to set an EOA as an important contract in the system error AddressIsNotContractException(address); /// @notice Thrown on attempting to receive a token that is not a collateral token or was forbidden error TokenNotAllowedException(); /// @notice Thrown on attempting to add a token that is already in a collateral list error TokenAlreadyAddedException(); /// @notice Thrown when attempting to use quota-related logic for a token that is not quoted in quota keeper error TokenIsNotQuotedException(); /// @notice Thrown on attempting to interact with an address that is not a valid target contract error TargetContractNotAllowedException(); /// @notice Thrown if function is not implemented error NotImplementedException(); // ------------------ // // CONTRACTS REGISTER // // ------------------ // /// @notice Thrown when an address is expected to be a registered credit manager, but is not error RegisteredCreditManagerOnlyException(); /// @notice Thrown when an address is expected to be a registered pool, but is not error RegisteredPoolOnlyException(); // ---------------- // // ADDRESS PROVIDER // // ---------------- // /// @notice Reverts if address key isn't found in address provider error AddressNotFoundException(); // ----------------- // // POOL, PQK, GAUGES // // ----------------- // /// @notice Thrown by pool-adjacent contracts when a credit manager being connected has a wrong pool address error IncompatibleCreditManagerException(); /// @notice Thrown when attempting to set an incompatible successor staking contract error IncompatibleSuccessorException(); /// @notice Thrown when attempting to vote in a non-approved contract error VotingContractNotAllowedException(); /// @notice Thrown when attempting to unvote more votes than there are error InsufficientVotesException(); /// @notice Thrown when attempting to borrow more than the second point on a two-point curve error BorrowingMoreThanU2ForbiddenException(); /// @notice Thrown when a credit manager attempts to borrow more than its limit in the current block, or in general error CreditManagerCantBorrowException(); /// @notice Thrown when attempting to connect a quota keeper to an incompatible pool error IncompatiblePoolQuotaKeeperException(); /// @notice Thrown when the quota is outside of min/max bounds error QuotaIsOutOfBoundsException(); // -------------- // // CREDIT MANAGER // // -------------- // /// @notice Thrown on failing a full collateral check after multicall error NotEnoughCollateralException(); /// @notice Thrown if an attempt to approve a collateral token to adapter's target contract fails error AllowanceFailedException(); /// @notice Thrown on attempting to perform an action for a credit account that does not exist error CreditAccountDoesNotExistException(); /// @notice Thrown on configurator attempting to add more than 255 collateral tokens error TooManyTokensException(); /// @notice Thrown if more than the maximum number of tokens were enabled on a credit account error TooManyEnabledTokensException(); /// @notice Thrown when attempting to execute a protocol interaction without active credit account set error ActiveCreditAccountNotSetException(); /// @notice Thrown when trying to update credit account's debt more than once in the same block error DebtUpdatedTwiceInOneBlockException(); /// @notice Thrown when trying to repay all debt while having active quotas error DebtToZeroWithActiveQuotasException(); /// @notice Thrown when a zero-debt account attempts to update quota error UpdateQuotaOnZeroDebtAccountException(); /// @notice Thrown when attempting to close an account with non-zero debt error CloseAccountWithNonZeroDebtException(); /// @notice Thrown when value of funds remaining on the account after liquidation is insufficient error InsufficientRemainingFundsException(); /// @notice Thrown when Credit Facade tries to write over a non-zero active Credit Account error ActiveCreditAccountOverridenException(); // ------------------- // // CREDIT CONFIGURATOR // // ------------------- // /// @notice Thrown on attempting to use a non-ERC20 contract or an EOA as a token error IncorrectTokenContractException(); /// @notice Thrown if the newly set LT if zero or greater than the underlying's LT error IncorrectLiquidationThresholdException(); /// @notice Thrown if borrowing limits are incorrect: minLimit > maxLimit or maxLimit > blockLimit error IncorrectLimitsException(); /// @notice Thrown if the new expiration date is less than the current expiration date or current timestamp error IncorrectExpirationDateException(); /// @notice Thrown if a contract returns a wrong credit manager or reverts when trying to retrieve it error IncompatibleContractException(); /// @notice Thrown if attempting to forbid an adapter that is not registered in the credit manager error AdapterIsNotRegisteredException(); // ------------- // // CREDIT FACADE // // ------------- // /// @notice Thrown when attempting to perform an action that is forbidden in whitelisted mode error ForbiddenInWhitelistedModeException(); /// @notice Thrown if credit facade is not expirable, and attempted aciton requires expirability error NotAllowedWhenNotExpirableException(); /// @notice Thrown if a selector that doesn't match any allowed function is passed to the credit facade in a multicall error UnknownMethodException(); /// @notice Thrown when trying to close an account with enabled tokens error CloseAccountWithEnabledTokensException(); /// @notice Thrown if a liquidator tries to liquidate an account with a health factor above 1 error CreditAccountNotLiquidatableException(); /// @notice Thrown if too much new debt was taken within a single block error BorrowedBlockLimitException(); /// @notice Thrown if the new debt principal for a credit account falls outside of borrowing limits error BorrowAmountOutOfLimitsException(); /// @notice Thrown if a user attempts to open an account via an expired credit facade error NotAllowedAfterExpirationException(); /// @notice Thrown if expected balances are attempted to be set twice without performing a slippage check error ExpectedBalancesAlreadySetException(); /// @notice Thrown if attempting to perform a slippage check when excepted balances are not set error ExpectedBalancesNotSetException(); /// @notice Thrown if balance of at least one token is less than expected during a slippage check error BalanceLessThanExpectedException(); /// @notice Thrown when trying to perform an action that is forbidden when credit account has enabled forbidden tokens error ForbiddenTokensException(); /// @notice Thrown when new forbidden tokens are enabled during the multicall error ForbiddenTokenEnabledException(); /// @notice Thrown when enabled forbidden token balance is increased during the multicall error ForbiddenTokenBalanceIncreasedException(); /// @notice Thrown when the remaining token balance is increased during the liquidation error RemainingTokenBalanceIncreasedException(); /// @notice Thrown if `botMulticall` is called by an address that is not approved by account owner or is forbidden error NotApprovedBotException(); /// @notice Thrown when attempting to perform a multicall action with no permission for it error NoPermissionException(uint256 permission); /// @notice Thrown when attempting to give a bot unexpected permissions error UnexpectedPermissionsException(); /// @notice Thrown when a custom HF parameter lower than 10000 is passed into the full collateral check error CustomHealthFactorTooLowException(); /// @notice Thrown when submitted collateral hint is not a valid token mask error InvalidCollateralHintException(); // ------ // // ACCESS // // ------ // /// @notice Thrown on attempting to call an access restricted function not as credit account owner error CallerNotCreditAccountOwnerException(); /// @notice Thrown on attempting to call an access restricted function not as configurator error CallerNotConfiguratorException(); /// @notice Thrown on attempting to call an access-restructed function not as account factory error CallerNotAccountFactoryException(); /// @notice Thrown on attempting to call an access restricted function not as credit manager error CallerNotCreditManagerException(); /// @notice Thrown on attempting to call an access restricted function not as credit facade error CallerNotCreditFacadeException(); /// @notice Thrown on attempting to call an access restricted function not as controller or configurator error CallerNotControllerException(); /// @notice Thrown on attempting to pause a contract without pausable admin rights error CallerNotPausableAdminException(); /// @notice Thrown on attempting to unpause a contract without unpausable admin rights error CallerNotUnpausableAdminException(); /// @notice Thrown on attempting to call an access restricted function not as gauge error CallerNotGaugeException(); /// @notice Thrown on attempting to call an access restricted function not as quota keeper error CallerNotPoolQuotaKeeperException(); /// @notice Thrown on attempting to call an access restricted function not as voter error CallerNotVoterException(); /// @notice Thrown on attempting to call an access restricted function not as allowed adapter error CallerNotAdapterException(); /// @notice Thrown on attempting to call an access restricted function not as migrator error CallerNotMigratorException(); /// @notice Thrown when an address that is not the designated executor attempts to execute a transaction error CallerNotExecutorException(); /// @notice Thrown on attempting to call an access restricted function not as veto admin error CallerNotVetoAdminException(); // ------------------- // // CONTROLLER TIMELOCK // // ------------------- // /// @notice Thrown when the new parameter values do not satisfy required conditions error ParameterChecksFailedException(); /// @notice Thrown when attempting to execute a non-queued transaction error TxNotQueuedException(); /// @notice Thrown when attempting to execute a transaction that is either immature or stale error TxExecutedOutsideTimeWindowException(); /// @notice Thrown when execution of a transaction fails error TxExecutionRevertedException(); /// @notice Thrown when the value of a parameter on execution is different from the value on queue error ParameterChangedAfterQueuedTxException(); // -------- // // BOT LIST // // -------- // /// @notice Thrown when attempting to set non-zero permissions for a forbidden or special bot error InvalidBotException(); // --------------- // // ACCOUNT FACTORY // // --------------- // /// @notice Thrown when trying to deploy second master credit account for a credit manager error MasterCreditAccountAlreadyDeployedException(); /// @notice Thrown when trying to rescue funds from a credit account that is currently in use error CreditAccountIsInUseException(); // ------------ // // PRICE ORACLE // // ------------ // /// @notice Thrown on attempting to set a token price feed to an address that is not a correct price feed error IncorrectPriceFeedException(); /// @notice Thrown on attempting to interact with a price feed for a token not added to the price oracle error PriceFeedDoesNotExistException(); /// @notice Thrown when price feed returns incorrect price for a token error IncorrectPriceException(); /// @notice Thrown when token's price feed becomes stale error StalePriceException();
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; import {IACL} from "@gearbox-protocol/core-v2/contracts/interfaces/IACL.sol"; import { CallerNotControllerException, CallerNotPausableAdminException, CallerNotUnpausableAdminException } from "../interfaces/IExceptions.sol"; import {ACLTrait} from "./ACLTrait.sol"; import {ReentrancyGuardTrait} from "./ReentrancyGuardTrait.sol"; /// @title ACL non-reentrant trait /// @notice Extended version of `ACLTrait` that implements pausable functionality, /// reentrancy protection and external controller role abstract contract ACLNonReentrantTrait is ACLTrait, Pausable, ReentrancyGuardTrait { /// @notice Emitted when new external controller is set event NewController(address indexed newController); /// @notice External controller address address public controller; /// @dev Ensures that function caller is external controller or configurator modifier controllerOnly() { _ensureCallerIsControllerOrConfigurator(); _; } /// @dev Reverts if the caller is not controller or configurator /// @dev Used to cut contract size on modifiers function _ensureCallerIsControllerOrConfigurator() internal view { if (msg.sender != controller && !_isConfigurator({account: msg.sender})) { revert CallerNotControllerException(); } } /// @dev Ensures that function caller has pausable admin role modifier pausableAdminsOnly() { _ensureCallerIsPausableAdmin(); _; } /// @dev Reverts if the caller is not pausable admin /// @dev Used to cut contract size on modifiers function _ensureCallerIsPausableAdmin() internal view { if (!_isPausableAdmin({account: msg.sender})) { revert CallerNotPausableAdminException(); } } /// @dev Ensures that function caller has unpausable admin role modifier unpausableAdminsOnly() { _ensureCallerIsUnpausableAdmin(); _; } /// @dev Reverts if the caller is not unpausable admin /// @dev Used to cut contract size on modifiers function _ensureCallerIsUnpausableAdmin() internal view { if (!_isUnpausableAdmin({account: msg.sender})) { revert CallerNotUnpausableAdminException(); } } /// @notice Constructor /// @param addressProvider Address provider contract address constructor(address addressProvider) ACLTrait(addressProvider) { controller = IACL(acl).owner(); } /// @notice Pauses contract, can only be called by an account with pausable admin role function pause() external virtual pausableAdminsOnly { _pause(); } /// @notice Unpauses contract, can only be called by an account with unpausable admin role function unpause() external virtual unpausableAdminsOnly { _unpause(); } /// @notice Sets new external controller, can only be called by configurator function setController(address newController) external configuratorOnly { if (controller == newController) return; controller = newController; emit NewController(newController); } /// @dev Checks whether given account has pausable admin role function _isPausableAdmin(address account) internal view returns (bool) { return IACL(acl).isPausableAdmin(account); } /// @dev Checks whether given account has unpausable admin role function _isUnpausableAdmin(address account) internal view returns (bool) { return IACL(acl).isUnpausableAdmin(account); } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; // Denominations uint256 constant WAD = 1e18; uint256 constant RAY = 1e27; uint16 constant PERCENTAGE_FACTOR = 1e4; //percentage plus two decimals // 25% of type(uint256).max uint256 constant ALLOWANCE_THRESHOLD = type(uint96).max >> 3; // FEE = 50% uint16 constant DEFAULT_FEE_INTEREST = 50_00; // 50% // LIQUIDATION_FEE 1.5% uint16 constant DEFAULT_FEE_LIQUIDATION = 1_50; // 1.5% // LIQUIDATION PREMIUM 4% uint16 constant DEFAULT_LIQUIDATION_PREMIUM = 4_00; // 4% // LIQUIDATION_FEE_EXPIRED 2% uint16 constant DEFAULT_FEE_LIQUIDATION_EXPIRED = 1_00; // 2% // LIQUIDATION PREMIUM EXPIRED 2% uint16 constant DEFAULT_LIQUIDATION_PREMIUM_EXPIRED = 2_00; // 2% // DEFAULT PROPORTION OF MAX BORROWED PER BLOCK TO MAX BORROWED PER ACCOUNT uint16 constant DEFAULT_LIMIT_PER_BLOCK_MULTIPLIER = 2; // Seconds in a year uint256 constant SECONDS_PER_YEAR = 365 days; uint256 constant SECONDS_PER_ONE_AND_HALF_YEAR = (SECONDS_PER_YEAR * 3) / 2; // OPERATIONS // Leverage decimals - 100 is equal to 2x leverage (100% * collateral amount + 100% * borrowed amount) uint8 constant LEVERAGE_DECIMALS = 100; // Maximum withdraw fee for pool in PERCENTAGE_FACTOR format uint8 constant MAX_WITHDRAW_FEE = 100; uint256 constant EXACT_INPUT = 1; uint256 constant EXACT_OUTPUT = 2; address constant UNIVERSAL_CONTRACT = 0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC;
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; /// @title Version interface /// @notice Defines contract version interface IVersion { /// @notice Contract version function version() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; struct MultiCall { address target; bytes callData; } library MultiCallOps { function copyMulticall(MultiCall memory call) internal pure returns (MultiCall memory) { return MultiCall({ target: call.target, callData: call.callData }); } function trim(MultiCall[] memory calls) internal pure returns (MultiCall[] memory trimmed) { uint256 len = calls.length; if (len == 0) return calls; uint256 foundLen; while (calls[foundLen].target != address(0)) { unchecked { ++foundLen; if (foundLen == len) return calls; } } if (foundLen > 0) return copy(calls, foundLen); } function copy(MultiCall[] memory calls, uint256 len) internal pure returns (MultiCall[] memory res) { res = new MultiCall[](len); for (uint256 i; i < len; ) { res[i] = copyMulticall(calls[i]); unchecked { ++i; } } } function clone(MultiCall[] memory calls) internal pure returns (MultiCall[] memory res) { return copy(calls, calls.length); } function append(MultiCall[] memory calls, MultiCall memory newCall) internal pure returns (MultiCall[] memory res) { uint256 len = calls.length; res = new MultiCall[](len + 1); for (uint256 i; i < len; ) { res[i] = copyMulticall(calls[i]); unchecked { ++i; } } res[len] = copyMulticall(newCall); } function prepend(MultiCall[] memory calls, MultiCall memory newCall) internal pure returns (MultiCall[] memory res) { uint256 len = calls.length; res = new MultiCall[](len + 1); res[0] = copyMulticall(newCall); for (uint256 i = 1; i < len + 1; ) { res[i] = copyMulticall(calls[i]); unchecked { ++i; } } } function concat(MultiCall[] memory calls1, MultiCall[] memory calls2) internal pure returns (MultiCall[] memory res) { uint256 len1 = calls1.length; uint256 lenTotal = len1 + calls2.length; if (lenTotal == calls1.length) return clone(calls1); if (lenTotal == calls2.length) return clone(calls2); res = new MultiCall[](lenTotal); for (uint256 i; i < lenTotal; ) { res[i] = (i < len1) ? copyMulticall(calls1[i]) : copyMulticall(calls2[i - len1]); unchecked { ++i; } } } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {BalanceDelta} from "../libraries/BalancesLogic.sol"; import {RevocationPair} from "./ICreditManagerV3.sol"; // ----------- // // PERMISSIONS // // ----------- // uint192 constant ADD_COLLATERAL_PERMISSION = 1; uint192 constant INCREASE_DEBT_PERMISSION = 1 << 1; uint192 constant DECREASE_DEBT_PERMISSION = 1 << 2; uint192 constant ENABLE_TOKEN_PERMISSION = 1 << 3; uint192 constant DISABLE_TOKEN_PERMISSION = 1 << 4; uint192 constant WITHDRAW_COLLATERAL_PERMISSION = 1 << 5; uint192 constant UPDATE_QUOTA_PERMISSION = 1 << 6; uint192 constant REVOKE_ALLOWANCES_PERMISSION = 1 << 7; uint192 constant EXTERNAL_CALLS_PERMISSION = 1 << 16; uint256 constant ALL_CREDIT_FACADE_CALLS_PERMISSION = ADD_COLLATERAL_PERMISSION | WITHDRAW_COLLATERAL_PERMISSION | INCREASE_DEBT_PERMISSION | DECREASE_DEBT_PERMISSION | ENABLE_TOKEN_PERMISSION | DISABLE_TOKEN_PERMISSION | UPDATE_QUOTA_PERMISSION | REVOKE_ALLOWANCES_PERMISSION; uint256 constant ALL_PERMISSIONS = ALL_CREDIT_FACADE_CALLS_PERMISSION | EXTERNAL_CALLS_PERMISSION; // ----- // // FLAGS // // ----- // /// @dev Indicates that there are enabled forbidden tokens on the account before multicall uint256 constant FORBIDDEN_TOKENS_BEFORE_CALLS = 1 << 192; /// @dev Indicates that external calls from credit account to adapters were made during multicall, /// set to true on the first call to the adapter uint256 constant EXTERNAL_CONTRACT_WAS_CALLED = 1 << 193; /// @title Credit facade V3 multicall interface /// @dev Unless specified otherwise, all these methods are only available in `openCreditAccount`, /// `closeCreditAccount`, `multicall`, and, with account owner's permission, `botMulticall` interface ICreditFacadeV3Multicall { /// @notice Updates the price for a token with on-demand updatable price feed /// @param token Token to push the price update for /// @param reserve Whether to update reserve price feed or main price feed /// @param data Data to call `updatePrice` with /// @dev Calls of this type must be placed before all other calls in the multicall not to revert /// @dev This method is available in all kinds of multicalls function onDemandPriceUpdate(address token, bool reserve, bytes calldata data) external; /// @notice Stores expected token balances (current balance + delta) after operations for a slippage check. /// Normally, a check is performed automatically at the end of the multicall, but more fine-grained /// behavior can be achieved by placing `storeExpectedBalances` and `compareBalances` where needed. /// @param balanceDeltas Array of (token, minBalanceDelta) pairs, deltas are allowed to be negative /// @dev Reverts if expected balances are already set /// @dev This method is available in all kinds of multicalls function storeExpectedBalances(BalanceDelta[] calldata balanceDeltas) external; /// @notice Performs a slippage check ensuring that current token balances are greater than saved expected ones /// @dev Resets stored expected balances /// @dev Reverts if expected balances are not stored /// @dev This method is available in all kinds of multicalls function compareBalances() external; /// @notice Adds collateral to account /// @param token Token to add /// @param amount Amount to add /// @dev Requires token approval from caller to the credit manager /// @dev This method can also be called during liquidation function addCollateral(address token, uint256 amount) external; /// @notice Adds collateral to account using signed EIP-2612 permit message /// @param token Token to add /// @param amount Amount to add /// @param deadline Permit deadline /// @dev `v`, `r`, `s` must be a valid signature of the permit message from caller to the credit manager /// @dev This method can also be called during liquidation function addCollateralWithPermit(address token, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /// @notice Increases account's debt /// @param amount Underlying amount to borrow /// @dev Increasing debt is prohibited when closing an account /// @dev Increasing debt is prohibited if it was previously updated in the same block /// @dev The resulting debt amount must be within allowed range /// @dev Increasing debt is prohibited if there are forbidden tokens enabled as collateral on the account /// @dev After debt increase, total amount borrowed by the credit manager in the current block must not exceed /// the limit defined in the facade function increaseDebt(uint256 amount) external; /// @notice Decreases account's debt /// @param amount Underlying amount to repay, value above account's total debt indicates full repayment /// @dev Decreasing debt is prohibited when opening an account /// @dev Decreasing debt is prohibited if it was previously updated in the same block /// @dev The resulting debt amount must be within allowed range or zero /// @dev Full repayment brings account into a special mode that skips collateral checks and thus requires /// an account to have no potential debt sources, e.g., all quotas must be disabled function decreaseDebt(uint256 amount) external; /// @notice Updates account's quota for a token /// @param token Token to update the quota for /// @param quotaChange Desired quota change in underlying token units (`type(int96).min` to disable quota) /// @param minQuota Minimum resulting account's quota for token required not to revert /// @dev Enables token as collateral if quota is increased from zero, disables if decreased to zero /// @dev Quota increase is prohibited if there are forbidden tokens enabled as collateral on the account /// @dev Quota update is prohibited if account has zero debt /// @dev Resulting account's quota for token must not exceed the limit defined in the facade function updateQuota(address token, int96 quotaChange, uint96 minQuota) external; /// @notice Withdraws collateral from account /// @param token Token to withdraw /// @param amount Amount to withdraw, `type(uint256).max` to withdraw all balance /// @param to Token recipient /// @dev This method can also be called during liquidation /// @dev Withdrawals are prohibited in multicalls if there are forbidden tokens enabled as collateral on the account /// @dev Withdrawals activate safe pricing (min of main and reserve feeds) in collateral check function withdrawCollateral(address token, uint256 amount, address to) external; /// @notice Sets advanced collateral check parameters /// @param collateralHints Optional array of token masks to check first to reduce the amount of computation /// when known subset of account's collateral tokens covers all the debt /// @param minHealthFactor Min account's health factor in bps in order not to revert, must be at least 10000 function setFullCheckParams(uint256[] calldata collateralHints, uint16 minHealthFactor) external; /// @notice Enables token as account's collateral, which makes it count towards account's total value /// @param token Token to enable as collateral /// @dev Enabling forbidden tokens is prohibited /// @dev Quoted tokens can only be enabled via `updateQuota`, this method is no-op for them function enableToken(address token) external; /// @notice Disables token as account's collateral /// @param token Token to disable as collateral /// @dev Quoted tokens can only be disabled via `updateQuota`, this method is no-op for them function disableToken(address token) external; /// @notice Revokes account's allowances for specified spender/token pairs /// @param revocations Array of spender/token pairs /// @dev Exists primarily to allow users to revoke allowances on accounts from old account factory on mainnet function revokeAdapterAllowances(RevocationPair[] calldata revocations) external; }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; enum AllowanceAction { FORBID, ALLOW } /// @notice Struct with credit manager configuration parameters /// @param minDebt Minimum debt amount per account /// @param maxDebt Maximum debt amount per account /// @param degenNFT Whether to apply Degen NFT whitelist logic /// @param expirable Whether facade must be expirable /// @param name Credit manager name struct CreditManagerOpts { uint128 minDebt; uint128 maxDebt; address degenNFT; bool expirable; string name; } interface ICreditConfiguratorV3Events { // ------ // // TOKENS // // ------ // /// @notice Emitted when a token is made recognizable as collateral in the credit manager event AddCollateralToken(address indexed token); /// @notice Emitted when a new collateral token liquidation threshold is set event SetTokenLiquidationThreshold(address indexed token, uint16 liquidationThreshold); /// @notice Emitted when a collateral token liquidation threshold ramping is scheduled event ScheduleTokenLiquidationThresholdRamp( address indexed token, uint16 liquidationThresholdInitial, uint16 liquidationThresholdFinal, uint40 timestampRampStart, uint40 timestampRampEnd ); /// @notice Emitted when a collateral token is forbidden event ForbidToken(address indexed token); /// @notice Emitted when a previously forbidden collateral token is allowed event AllowToken(address indexed token); /// @notice Emitted when a token is made quoted event QuoteToken(address indexed token); // -------- // // ADAPTERS // // -------- // /// @notice Emitted when a new adapter and its target contract are allowed in the credit manager event AllowAdapter(address indexed targetContract, address indexed adapter); /// @notice Emitted when adapter and its target contract are forbidden in the credit manager event ForbidAdapter(address indexed targetContract, address indexed adapter); // -------------- // // CREDIT MANAGER // // -------------- // /// @notice Emitted when a new maximum number of enabled tokens is set in the credit manager event SetMaxEnabledTokens(uint8 maxEnabledTokens); /// @notice Emitted when new fee parameters are set in the credit manager event UpdateFees( uint16 feeInterest, uint16 feeLiquidation, uint16 liquidationPremium, uint16 feeLiquidationExpired, uint16 liquidationPremiumExpired ); // -------- // // UPGRADES // // -------- // /// @notice Emitted when a new price oracle is set in the credit manager event SetPriceOracle(address indexed priceOracle); /// @notice Emitted when a new bot list is set in the credit facade event SetBotList(address indexed botList); /// @notice Emitted when a new facade is connected to the credit manager event SetCreditFacade(address indexed creditFacade); /// @notice Emitted when credit manager's configurator contract is upgraded event CreditConfiguratorUpgraded(address indexed creditConfigurator); // ------------- // // CREDIT FACADE // // ------------- // /// @notice Emitted when new debt principal limits are set event SetBorrowingLimits(uint256 minDebt, uint256 maxDebt); /// @notice Emitted when a new max debt per block multiplier is set event SetMaxDebtPerBlockMultiplier(uint8 maxDebtPerBlockMultiplier); /// @notice Emitted when a new max cumulative loss is set event SetMaxCumulativeLoss(uint128 maxCumulativeLoss); /// @notice Emitted when cumulative loss is reset to zero in the credit facade event ResetCumulativeLoss(); /// @notice Emitted when a new expiration timestamp is set in the credit facade event SetExpirationDate(uint40 expirationDate); /// @notice Emitted when an address is added to the list of emergency liquidators event AddEmergencyLiquidator(address indexed liquidator); /// @notice Emitted when an address is removed from the list of emergency liquidators event RemoveEmergencyLiquidator(address indexed liquidator); } /// @title Credit configurator V3 interface interface ICreditConfiguratorV3 is IVersion, ICreditConfiguratorV3Events { function addressProvider() external view returns (address); function creditManager() external view returns (address); function creditFacade() external view returns (address); function underlying() external view returns (address); // ------ // // TOKENS // // ------ // function addCollateralToken(address token, uint16 liquidationThreshold) external; function setLiquidationThreshold(address token, uint16 liquidationThreshold) external; function rampLiquidationThreshold( address token, uint16 liquidationThresholdFinal, uint40 rampStart, uint24 rampDuration ) external; function forbidToken(address token) external; function allowToken(address token) external; function makeTokenQuoted(address token) external; // -------- // // ADAPTERS // // -------- // function allowedAdapters() external view returns (address[] memory); function allowAdapter(address adapter) external; function forbidAdapter(address adapter) external; // -------------- // // CREDIT MANAGER // // -------------- // function setFees( uint16 feeInterest, uint16 feeLiquidation, uint16 liquidationPremium, uint16 feeLiquidationExpired, uint16 liquidationPremiumExpired ) external; function setMaxEnabledTokens(uint8 newMaxEnabledTokens) external; // -------- // // UPGRADES // // -------- // function setPriceOracle(uint256 newVersion) external; function setBotList(uint256 newVersion) external; function setCreditFacade(address newCreditFacade, bool migrateParams) external; function upgradeCreditConfigurator(address newCreditConfigurator) external; // ------------- // // CREDIT FACADE // // ------------- // function setMinDebtLimit(uint128 newMinDebt) external; function setMaxDebtLimit(uint128 newMaxDebt) external; function setMaxDebtPerBlockMultiplier(uint8 newMaxDebtLimitPerBlockMultiplier) external; function forbidBorrowing() external; function setMaxCumulativeLoss(uint128 newMaxCumulativeLoss) external; function resetCumulativeLoss() external; function setExpirationDate(uint40 newExpirationDate) external; function emergencyLiquidators() external view returns (address[] memory); function addEmergencyLiquidator(address liquidator) external; function removeEmergencyLiquidator(address liquidator) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol"; import "../token/ERC20/extensions/IERC20Metadata.sol"; /** * @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626]. * * _Available since v4.7._ */ interface IERC4626 is IERC20, IERC20Metadata { event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); event Withdraw( address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /** * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. * * - MUST be an ERC-20 token contract. * - MUST NOT revert. */ function asset() external view returns (address assetTokenAddress); /** * @dev Returns the total amount of the underlying asset that is “managed” by Vault. * * - SHOULD include any compounding that occurs from yield. * - MUST be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT revert. */ function totalAssets() external view returns (uint256 totalManagedAssets); /** * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToShares(uint256 assets) external view returns (uint256 shares); /** * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal * scenario where all the conditions are met. * * - MUST NOT be inclusive of any fees that are charged against assets in the Vault. * - MUST NOT show any variations depending on the caller. * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. * - MUST NOT revert. * * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and * from. */ function convertToAssets(uint256 shares) external view returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, * through a deposit call. * * - MUST return a limited value if receiver is subject to some deposit limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. * - MUST NOT revert. */ function maxDeposit(address receiver) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given * current on-chain conditions. * * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called * in the same transaction. * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the * deposit would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewDeposit(uint256 assets) external view returns (uint256 shares); /** * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * deposit execution, and are accounted for during deposit. * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function deposit(uint256 assets, address receiver) external returns (uint256 shares); /** * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. * - MUST return a limited value if receiver is subject to some mint limit. * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. * - MUST NOT revert. */ function maxMint(address receiver) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given * current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the * same transaction. * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint * would be accepted, regardless if the user has enough tokens approved, etc. * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by minting. */ function previewMint(uint256 shares) external view returns (uint256 assets); /** * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. * * - MUST emit the Deposit event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint * execution, and are accounted for during mint. * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not * approving enough underlying tokens to the Vault contract, etc). * * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. */ function mint(uint256 shares, address receiver) external returns (uint256 assets); /** * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the * Vault, through a withdraw call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST NOT revert. */ function maxWithdraw(address owner) external view returns (uint256 maxAssets); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, * given current on-chain conditions. * * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if * called * in the same transaction. * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though * the withdrawal would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by depositing. */ function previewWithdraw(uint256 assets) external view returns (uint256 shares); /** * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * withdraw execution, and are accounted for during withdraw. * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); /** * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, * through a redeem call. * * - MUST return a limited value if owner is subject to some withdrawal limit or timelock. * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. * - MUST NOT revert. */ function maxRedeem(address owner) external view returns (uint256 maxShares); /** * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, * given current on-chain conditions. * * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the * same transaction. * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the * redemption would be accepted, regardless if the user has enough shares, etc. * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. * - MUST NOT revert. * * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in * share price or some other type of condition, meaning the depositor will lose assets by redeeming. */ function previewRedeem(uint256 shares) external view returns (uint256 assets); /** * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver. * * - MUST emit the Withdraw event. * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the * redeem execution, and are accounted for during redeem. * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner * not having enough shares, etc). * * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. * Those methods should be performed separately. */ function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; interface IVotingContractV3 { function vote(address user, uint96 votes, bytes calldata extraData) external; function unvote(address user, uint96 votes, bytes calldata extraData) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; import { IVersion } from "./IVersion.sol"; interface IACLExceptions { /// @dev Thrown when attempting to delete an address from a set that is not a pausable admin error AddressNotPausableAdminException(address addr); /// @dev Thrown when attempting to delete an address from a set that is not a unpausable admin error AddressNotUnpausableAdminException(address addr); } interface IACLEvents { /// @dev Emits when a new admin is added that can pause contracts event PausableAdminAdded(address indexed newAdmin); /// @dev Emits when a Pausable admin is removed event PausableAdminRemoved(address indexed admin); /// @dev Emits when a new admin is added that can unpause contracts event UnpausableAdminAdded(address indexed newAdmin); /// @dev Emits when an Unpausable admin is removed event UnpausableAdminRemoved(address indexed admin); } /// @title ACL interface interface IACL is IACLEvents, IACLExceptions, IVersion { /// @dev Returns true if the address is a pausable admin and false if not /// @param addr Address to check function isPausableAdmin(address addr) external view returns (bool); /// @dev Returns true if the address is unpausable admin and false if not /// @param addr Address to check function isUnpausableAdmin(address addr) external view returns (bool); /// @dev Returns true if an address has configurator rights /// @param account Address to check function isConfigurator(address account) external view returns (bool); /// @dev Returns address of configurator function owner() external view returns (address); }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IACL} from "@gearbox-protocol/core-v2/contracts/interfaces/IACL.sol"; import {AP_ACL, IAddressProviderV3, NO_VERSION_CONTROL} from "../interfaces/IAddressProviderV3.sol"; import {CallerNotConfiguratorException} from "../interfaces/IExceptions.sol"; import {SanityCheckTrait} from "./SanityCheckTrait.sol"; /// @title ACL trait /// @notice Utility class for ACL (access-control list) consumers abstract contract ACLTrait is SanityCheckTrait { /// @notice ACL contract address address public immutable acl; /// @notice Constructor /// @param addressProvider Address provider contract address constructor(address addressProvider) nonZeroAddress(addressProvider) { acl = IAddressProviderV3(addressProvider).getAddressOrRevert(AP_ACL, NO_VERSION_CONTROL); } /// @dev Ensures that function caller has configurator role modifier configuratorOnly() { _ensureCallerIsConfigurator(); _; } /// @dev Reverts if the caller is not the configurator /// @dev Used to cut contract size on modifiers function _ensureCallerIsConfigurator() internal view { if (!_isConfigurator({account: msg.sender})) { revert CallerNotConfiguratorException(); } } /// @dev Checks whether given account has configurator role function _isConfigurator(address account) internal view returns (bool) { return IACL(acl).isConfigurator(account); } }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; uint8 constant NOT_ENTERED = 1; uint8 constant ENTERED = 2; /// @title Reentrancy guard trait /// @notice Same as OpenZeppelin's `ReentrancyGuard` but only uses 1 byte of storage instead of 32 abstract contract ReentrancyGuardTrait { uint8 internal _reentrancyStatus = NOT_ENTERED; /// @dev Prevents a contract from calling itself, directly or indirectly. /// Calling a `nonReentrant` function from another `nonReentrant` /// function is not supported. It is possible to prevent this from happening /// by making the `nonReentrant` function external, and making it call a /// `private` function that does the actual work. modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true _ensureNotEntered(); // Any calls to nonReentrant after this point will fail _reentrancyStatus = ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _reentrancyStatus = NOT_ENTERED; } /// @dev Reverts if the contract is currently entered /// @dev Used to cut contract size on modifiers function _ensureNotEntered() internal view { require(_reentrancyStatus != ENTERED, "ReentrancyGuard: reentrant call"); } }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {SafeERC20} from "@1inch/solidity-utils/contracts/libraries/SafeERC20.sol"; import {BitMask} from "./BitMask.sol"; import {Balance} from "@gearbox-protocol/core-v2/contracts/libraries/Balances.sol"; struct BalanceWithMask { address token; uint256 tokenMask; uint256 balance; } struct BalanceDelta { address token; int256 amount; } enum Comparison { GREATER, LESS } /// @title Balances logic library /// @notice Implements functions for before-and-after balance comparisons library BalancesLogic { using BitMask for uint256; using SafeCast for int256; using SafeCast for uint256; using SafeERC20 for IERC20; /// @dev Compares current `token` balance with `value` /// @param token Token to check balance for /// @param value Value to compare current token balance with /// @param comparison Whether current balance must be greater/less than or equal to `value` function checkBalance(address creditAccount, address token, uint256 value, Comparison comparison) internal view returns (bool) { uint256 current = IERC20(token).safeBalanceOf(creditAccount); return (comparison == Comparison.GREATER && current >= value) || (comparison == Comparison.LESS && current <= value); // U:[BLL-1] } /// @dev Returns an array of expected token balances after operations /// @param creditAccount Credit account to compute balances for /// @param deltas Array of expected token balance changes function storeBalances(address creditAccount, BalanceDelta[] memory deltas) internal view returns (Balance[] memory balances) { uint256 len = deltas.length; balances = new Balance[](len); // U:[BLL-2] for (uint256 i = 0; i < len;) { int256 balance = IERC20(deltas[i].token).safeBalanceOf(creditAccount).toInt256(); balances[i] = Balance({token: deltas[i].token, balance: (balance + deltas[i].amount).toUint256()}); // U:[BLL-2] unchecked { ++i; } } } /// @dev Compares current balances with the previously stored ones /// @param creditAccount Credit account to compare balances for /// @param balances Array of previously stored balances /// @param comparison Whether current balances must be greater/less than or equal to stored ones /// @return success True if condition specified by `comparison` holds for all tokens, false otherwise function compareBalances(address creditAccount, Balance[] memory balances, Comparison comparison) internal view returns (bool success) { uint256 len = balances.length; unchecked { for (uint256 i = 0; i < len; ++i) { if (!BalancesLogic.checkBalance(creditAccount, balances[i].token, balances[i].balance, comparison)) { return false; // U:[BLL-3] } } } return true; // U:[BLL-3] } /// @dev Returns balances of specified tokens on the credit account /// @param creditAccount Credit account to compute balances for /// @param tokensMask Bit mask of tokens to compute balances for /// @param getTokenByMaskFn Function that returns token's address by its mask function storeBalances( address creditAccount, uint256 tokensMask, function (uint256) view returns (address) getTokenByMaskFn ) internal view returns (BalanceWithMask[] memory balances) { if (tokensMask == 0) return balances; balances = new BalanceWithMask[](tokensMask.calcEnabledTokens()); // U:[BLL-4] unchecked { uint256 i; while (tokensMask != 0) { uint256 tokenMask = tokensMask & uint256(-int256(tokensMask)); tokensMask ^= tokenMask; address token = getTokenByMaskFn(tokenMask); balances[i] = BalanceWithMask({ token: token, tokenMask: tokenMask, balance: IERC20(token).safeBalanceOf(creditAccount) }); // U:[BLL-4] ++i; } } } /// @dev Compares current balances of specified tokens with the previously stored ones /// @param creditAccount Credit account to compare balances for /// @param tokensMask Bit mask of tokens to compare balances for /// @param balances Array of previously stored balances /// @param comparison Whether current balances must be greater/less than or equal to stored ones /// @return success True if condition specified by `comparison` holds for all tokens, false otherwise function compareBalances( address creditAccount, uint256 tokensMask, BalanceWithMask[] memory balances, Comparison comparison ) internal view returns (bool) { if (tokensMask == 0) return true; unchecked { uint256 len = balances.length; for (uint256 i; i < len; ++i) { if (tokensMask & balances[i].tokenMask != 0) { if (!BalancesLogic.checkBalance(creditAccount, balances[i].token, balances[i].balance, comparison)) { return false; // U:[BLL-5] } } } } return true; // U:[BLL-5] } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IVersion} from "@gearbox-protocol/core-v2/contracts/interfaces/IVersion.sol"; uint256 constant NO_VERSION_CONTROL = 0; bytes32 constant AP_CONTRACTS_REGISTER = "CONTRACTS_REGISTER"; bytes32 constant AP_ACL = "ACL"; bytes32 constant AP_PRICE_ORACLE = "PRICE_ORACLE"; bytes32 constant AP_ACCOUNT_FACTORY = "ACCOUNT_FACTORY"; bytes32 constant AP_DATA_COMPRESSOR = "DATA_COMPRESSOR"; bytes32 constant AP_TREASURY = "TREASURY"; bytes32 constant AP_GEAR_TOKEN = "GEAR_TOKEN"; bytes32 constant AP_WETH_TOKEN = "WETH_TOKEN"; bytes32 constant AP_WETH_GATEWAY = "WETH_GATEWAY"; bytes32 constant AP_ROUTER = "ROUTER"; bytes32 constant AP_BOT_LIST = "BOT_LIST"; bytes32 constant AP_GEAR_STAKING = "GEAR_STAKING"; bytes32 constant AP_ZAPPER_REGISTER = "ZAPPER_REGISTER"; interface IAddressProviderV3Events { /// @notice Emitted when an address is set for a contract key event SetAddress(bytes32 indexed key, address indexed value, uint256 indexed version); } /// @title Address provider V3 interface interface IAddressProviderV3 is IAddressProviderV3Events, IVersion { function addresses(bytes32 key, uint256 _version) external view returns (address); function getAddressOrRevert(bytes32 key, uint256 _version) external view returns (address result); function setAddress(bytes32 key, address value, bool saveVersion) external; }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {ZeroAddressException} from "../interfaces/IExceptions.sol"; /// @title Sanity check trait abstract contract SanityCheckTrait { /// @dev Ensures that passed address is non-zero modifier nonZeroAddress(address addr) { _revertIfZeroAddress(addr); _; } /// @dev Reverts if address is zero function _revertIfZeroAddress(address addr) private pure { if (addr == address(0)) revert ZeroAddressException(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; import "../interfaces/IDaiLikePermit.sol"; import "../interfaces/IPermit2.sol"; import "../interfaces/IWETH.sol"; import "../libraries/RevertReasonForwarder.sol"; /// @title Implements efficient safe methods for ERC20 interface. library SafeERC20 { error SafeTransferFailed(); error SafeTransferFromFailed(); error ForceApproveFailed(); error SafeIncreaseAllowanceFailed(); error SafeDecreaseAllowanceFailed(); error SafePermitBadLength(); error Permit2TransferAmountTooHigh(); address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857; // SafePermitBadLength.selector uint256 private constant _RAW_CALL_GAS_LIMIT = 5000; function safeBalanceOf( IERC20 token, address account ) internal view returns(uint256 tokenBalance) { bytes4 selector = IERC20.balanceOf.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0x00, selector) mstore(0x04, account) let success := staticcall(gas(), token, 0x00, 0x24, 0x00, 0x20) tokenBalance := mload(0) if or(iszero(success), lt(returndatasize(), 0x20)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract. function safeTransferFromUniversal( IERC20 token, address from, address to, uint256 amount, bool permit2 ) internal { if (permit2) { safeTransferFromPermit2(token, from, to, amount); } else { safeTransferFrom(token, from, to, amount); } } /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract. function safeTransferFrom( IERC20 token, address from, address to, uint256 amount ) internal { bytes4 selector = token.transferFrom.selector; bool success; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) success := call(gas(), token, 0, data, 100, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } if (!success) revert SafeTransferFromFailed(); } /// @dev Permit2 version of safeTransferFrom above. function safeTransferFromPermit2( IERC20 token, address from, address to, uint256 amount ) internal { if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh(); bytes4 selector = IPermit2.transferFrom.selector; bool success; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) mstore(add(data, 0x64), token) success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0) if success { success := gt(extcodesize(_PERMIT2), 0) } } if (!success) revert SafeTransferFromFailed(); } /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract. function safeTransfer( IERC20 token, address to, uint256 value ) internal { if (!_makeCall(token, token.transfer.selector, to, value)) { revert SafeTransferFailed(); } } /// @dev If `approve(from, to, amount)` fails, try to `approve(from, to, 0)` before retry. function forceApprove( IERC20 token, address spender, uint256 value ) internal { if (!_makeCall(token, token.approve.selector, spender, value)) { if ( !_makeCall(token, token.approve.selector, spender, 0) || !_makeCall(token, token.approve.selector, spender, value) ) { revert ForceApproveFailed(); } } } /// @dev Allowance increase with safe math check. function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 allowance = token.allowance(address(this), spender); if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed(); forceApprove(token, spender, allowance + value); } /// @dev Allowance decrease with safe math check. function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 allowance = token.allowance(address(this), spender); if (value > allowance) revert SafeDecreaseAllowanceFailed(); forceApprove(token, spender, allowance - value); } function safePermit(IERC20 token, bytes calldata permit) internal { if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert(); } function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal { if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert(); } function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) { return tryPermit(token, msg.sender, address(this), permit); } function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) { bytes4 permitSelector = IERC20Permit.permit.selector; bytes4 daiPermitSelector = IDaiLikePermit.permit.selector; bytes4 permit2Selector = IPermit2.permit.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) switch permit.length case 100 { mstore(ptr, permitSelector) mstore(add(ptr, 0x04), owner) mstore(add(ptr, 0x24), spender) // Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs) { // stack too deep let deadline := shr(224, calldataload(add(permit.offset, 0x20))) let vs := calldataload(add(permit.offset, 0x44)) calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // value mstore(add(ptr, 0x64), sub(deadline, 1)) mstore(add(ptr, 0x84), add(27, shr(255, vs))) calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // r mstore(add(ptr, 0xc4), shr(1, shl(1, vs))) } // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0xe4, 0, 0) } case 72 { mstore(ptr, daiPermitSelector) mstore(add(ptr, 0x04), owner) mstore(add(ptr, 0x24), spender) // Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs) { // stack too deep let expiry := shr(224, calldataload(add(permit.offset, 0x04))) let vs := calldataload(add(permit.offset, 0x28)) mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) mstore(add(ptr, 0x64), sub(expiry, 1)) mstore(add(ptr, 0x84), true) mstore(add(ptr, 0xa4), add(27, shr(255, vs))) calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // r mstore(add(ptr, 0xe4), shr(1, shl(1, vs))) } // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0x104, 0, 0) } case 224 { mstore(ptr, permitSelector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0xe4, 0, 0) } case 256 { mstore(ptr, daiPermitSelector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0x104, 0, 0) } case 96 { // Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs) mstore(ptr, permit2Selector) mstore(add(ptr, 0x04), owner) mstore(add(ptr, 0x24), token) calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // amount mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // expiration mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // nonce mstore(add(ptr, 0xa4), spender) mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // sigDeadline mstore(add(ptr, 0xe4), 0x100) mstore(add(ptr, 0x104), 0x40) calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // r calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // vs // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0) } case 352 { mstore(ptr, permit2Selector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0) } default { mstore(ptr, _PERMIT_LENGTH_ERROR) revert(ptr, 4) } } } function _makeCall( IERC20 token, bytes4 selector, address to, uint256 amount ) private returns (bool success) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), to) mstore(add(data, 0x24), amount) success := call(gas(), token, 0, data, 0x44, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } } function safeDeposit(IWETH weth, uint256 amount) internal { if (amount > 0) { bytes4 selector = IWETH.deposit.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0, selector) if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } } } } function safeWithdraw(IWETH weth, uint256 amount) internal { bytes4 selector = IWETH.withdraw.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0, selector) mstore(4, amount) if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal { safeWithdraw(weth, amount); if (to != address(this)) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly if iszero(call(_RAW_CALL_GAS_LIMIT, to, amount, 0, 0, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } } }
// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2023. pragma solidity ^0.8.17; import {IncorrectParameterException} from "../interfaces/IExceptions.sol"; uint256 constant UNDERLYING_TOKEN_MASK = 1; /// @title Bit mask library /// @notice Implements functions that manipulate bit masks /// Bit masks are utilized extensively by Gearbox to efficiently store token sets (enabled tokens on accounts /// or forbidden tokens) and check for set inclusion. A mask is a uint256 number that has its i-th bit set to /// 1 if i-th item is included into the set. For example, each token has a mask equal to 2**i, so set inclusion /// can be checked by checking tokenMask & setMask != 0. library BitMask { /// @dev Calculates an index of an item based on its mask (using a binary search) /// @dev The input should always have only 1 bit set, otherwise the result may be unpredictable function calcIndex(uint256 mask) internal pure returns (uint8 index) { if (mask == 0) revert IncorrectParameterException(); // U:[BM-1] uint16 lb = 0; // U:[BM-2] uint16 ub = 256; // U:[BM-2] uint16 mid = 128; // U:[BM-2] unchecked { while (true) { uint256 newMask = 1 << mid; if (newMask & mask != 0) return uint8(mid); // U:[BM-2] if (newMask > mask) ub = mid; // U:[BM-2] else lb = mid; // U:[BM-2] mid = (lb + ub) >> 1; // U:[BM-2] } } } /// @dev Calculates the number of `1` bits /// @param enabledTokensMask Bit mask to compute the number of `1` bits in function calcEnabledTokens(uint256 enabledTokensMask) internal pure returns (uint256 totalTokensEnabled) { unchecked { while (enabledTokensMask > 0) { enabledTokensMask &= enabledTokensMask - 1; // U:[BM-3] ++totalTokensEnabled; // U:[BM-3] } } } /// @dev Enables bits from the second mask in the first mask /// @param enabledTokenMask The initial mask /// @param bitsToEnable Mask of bits to enable function enable(uint256 enabledTokenMask, uint256 bitsToEnable) internal pure returns (uint256) { return enabledTokenMask | bitsToEnable; // U:[BM-4] } /// @dev Disables bits from the second mask in the first mask /// @param enabledTokenMask The initial mask /// @param bitsToDisable Mask of bits to disable function disable(uint256 enabledTokenMask, uint256 bitsToDisable) internal pure returns (uint256) { return enabledTokenMask & ~bitsToDisable; // U:[BM-4] } /// @dev Computes a new mask with sets of new enabled and disabled bits /// @dev bitsToEnable and bitsToDisable are applied sequentially to original mask /// @param enabledTokensMask The initial mask /// @param bitsToEnable Mask with bits to enable /// @param bitsToDisable Mask with bits to disable function enableDisable(uint256 enabledTokensMask, uint256 bitsToEnable, uint256 bitsToDisable) internal pure returns (uint256) { return (enabledTokensMask | bitsToEnable) & (~bitsToDisable); // U:[BM-5] } /// @dev Enables bits from the second mask in the first mask, skipping specified bits /// @param enabledTokenMask The initial mask /// @param bitsToEnable Mask with bits to enable /// @param invertedSkipMask An inversion of mask of immutable bits function enable(uint256 enabledTokenMask, uint256 bitsToEnable, uint256 invertedSkipMask) internal pure returns (uint256) { return enabledTokenMask | (bitsToEnable & invertedSkipMask); // U:[BM-6] } /// @dev Disables bits from the second mask in the first mask, skipping specified bits /// @param enabledTokenMask The initial mask /// @param bitsToDisable Mask with bits to disable /// @param invertedSkipMask An inversion of mask of immutable bits function disable(uint256 enabledTokenMask, uint256 bitsToDisable, uint256 invertedSkipMask) internal pure returns (uint256) { return enabledTokenMask & (~(bitsToDisable & invertedSkipMask)); // U:[BM-6] } /// @dev Computes a new mask with sets of new enabled and disabled bits, skipping some bits /// @dev bitsToEnable and bitsToDisable are applied sequentially to original mask. Skipmask is applied in both cases. /// @param enabledTokensMask The initial mask /// @param bitsToEnable Mask with bits to enable /// @param bitsToDisable Mask with bits to disable /// @param invertedSkipMask An inversion of mask of immutable bits function enableDisable( uint256 enabledTokensMask, uint256 bitsToEnable, uint256 bitsToDisable, uint256 invertedSkipMask ) internal pure returns (uint256) { return (enabledTokensMask | (bitsToEnable & invertedSkipMask)) & (~(bitsToDisable & invertedSkipMask)); // U:[BM-7] } }
// SPDX-License-Identifier: MIT // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Holdings, 2022 pragma solidity ^0.8.10; struct Balance { address token; uint256 balance; } library BalanceOps { error UnknownToken(address); function copyBalance(Balance memory b) internal pure returns (Balance memory) { return Balance({ token: b.token, balance: b.balance }); } function addBalance( Balance[] memory b, address token, uint256 amount ) internal pure { b[getIndex(b, token)].balance += amount; } function subBalance( Balance[] memory b, address token, uint256 amount ) internal pure { b[getIndex(b, token)].balance -= amount; } function getBalance(Balance[] memory b, address token) internal pure returns (uint256 amount) { return b[getIndex(b, token)].balance; } function setBalance( Balance[] memory b, address token, uint256 amount ) internal pure { b[getIndex(b, token)].balance = amount; } function getIndex(Balance[] memory b, address token) internal pure returns (uint256 index) { for (uint256 i; i < b.length; ) { if (b[i].token == token) { return i; } unchecked { ++i; } } revert UnknownToken(token); } function copy(Balance[] memory b, uint256 len) internal pure returns (Balance[] memory res) { res = new Balance[](len); for (uint256 i; i < len; ) { res[i] = copyBalance(b[i]); unchecked { ++i; } } } function clone(Balance[] memory b) internal pure returns (Balance[] memory) { return copy(b, b.length); } function getModifiedAfterSwap( Balance[] memory b, address tokenFrom, uint256 amountFrom, address tokenTo, uint256 amountTo ) internal pure returns (Balance[] memory res) { res = copy(b, b.length); setBalance(res, tokenFrom, getBalance(b, tokenFrom) - amountFrom); setBalance(res, tokenTo, getBalance(b, tokenTo) + amountTo); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; // EIP-2612 is Final as of 2022-11-01. This file is deprecated. import "./IERC20Permit.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IDaiLikePermit { function permit( address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPermit2 { struct PermitDetails { // ERC20 token address address token; // the maximum amount allowed to spend uint160 amount; // timestamp at which a spender's token allowances become invalid uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } /// @notice The permit message signed for a single token allownce struct PermitSingle { // the permit data for a single token alownce PermitDetails details; // address permissioned on the allowed tokens address spender; // deadline on the permit signature uint256 sigDeadline; } /// @notice Packed allowance struct PackedAllowance { // amount allowed uint160 amount; // permission expiry uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } function transferFrom(address user, address spender, uint160 amount, address token) external; function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external; function allowance(address user, address token, address spender) external view returns (PackedAllowance memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Revert reason forwarder. library RevertReasonForwarder { /// @dev Forwards latest externall call revert. function reRevert() internal pure { // bubble up revert reason from latest external call assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } }
{ "remappings": [ "@1inch/=node_modules/@1inch/", "@arbitrum/=node_modules/@arbitrum/", "@chainlink/=node_modules/@chainlink/", "@eth-optimism/=node_modules/@eth-optimism/", "@gearbox-protocol/=node_modules/@gearbox-protocol/", "@openzeppelin/=node_modules/@openzeppelin/", "@redstone-finance/=node_modules/@redstone-finance/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 1000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_addressProvider","type":"address"},{"internalType":"address","name":"_vetoAdmin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotConfiguratorException","type":"error"},{"inputs":[],"name":"CallerNotExecutorException","type":"error"},{"inputs":[],"name":"CallerNotPausableAdminException","type":"error"},{"inputs":[],"name":"CallerNotUnpausableAdminException","type":"error"},{"inputs":[],"name":"CallerNotVetoAdminException","type":"error"},{"inputs":[],"name":"ParameterChangedAfterQueuedTxException","type":"error"},{"inputs":[],"name":"ParameterChecksFailedException","type":"error"},{"inputs":[],"name":"TxExecutedOutsideTimeWindowException","type":"error"},{"inputs":[],"name":"TxExecutionRevertedException","type":"error"},{"inputs":[],"name":"TxNotQueuedException","type":"error"},{"inputs":[],"name":"ZeroAddressException","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"CancelTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"ExecuteTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newController","type":"address"}],"name":"NewController","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"string","name":"signature","type":"string"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"uint40","name":"eta","type":"uint40"}],"name":"QueueTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"string","name":"group","type":"string"}],"name":"SetGroup","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"policyHash","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"SetPolicy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"SetVetoAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"GRACE_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acl","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"cancelTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"policyHash","type":"bytes32"}],"name":"disablePolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"executeTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"address","name":"adapter","type":"address"}],"name":"forbidAdapter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"priceFeed","type":"address"}],"name":"forbidBoundsUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"creditManager","type":"address"}],"name":"getCreditManagerDebtLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditFacade","type":"address"}],"name":"getExpirationDate","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"getGroup","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getLTRampParamsHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditFacade","type":"address"}],"name":"getMaxDebtLimit","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditFacade","type":"address"}],"name":"getMaxDebtPerBlockMultiplier","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getMaxQuotaRate","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditFacade","type":"address"}],"name":"getMinDebtLimit","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getMinQuotaRate","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"policyHash","type":"bytes32"}],"name":"getPolicy","outputs":[{"components":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint40","name":"delay","type":"uint40"},{"internalType":"uint8","name":"flags","type":"uint8"},{"internalType":"uint256","name":"exactValue","type":"uint256"},{"internalType":"uint256","name":"minValue","type":"uint256"},{"internalType":"uint256","name":"maxValue","type":"uint256"},{"internalType":"uint256","name":"referencePoint","type":"uint256"},{"internalType":"uint40","name":"referencePointUpdatePeriod","type":"uint40"},{"internalType":"uint40","name":"referencePointTimestampLU","type":"uint40"},{"internalType":"uint16","name":"minPctChangeDown","type":"uint16"},{"internalType":"uint16","name":"minPctChangeUp","type":"uint16"},{"internalType":"uint16","name":"maxPctChangeDown","type":"uint16"},{"internalType":"uint16","name":"maxPctChangeUp","type":"uint16"},{"internalType":"uint256","name":"minChange","type":"uint256"},{"internalType":"uint256","name":"maxChange","type":"uint256"}],"internalType":"struct Policy","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"priceFeed","type":"address"}],"name":"getPriceFeedLowerBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"poolQuotaKeeper","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getTokenLimit","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"poolQuotaKeeper","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getTokenQuotaIncreaseFee","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"getTotalDebtLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"getWithdrawFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"queuedTransactions","outputs":[{"internalType":"bool","name":"queued","type":"bool"},{"internalType":"address","name":"executor","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint40","name":"eta","type":"uint40"},{"internalType":"string","name":"signature","type":"string"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"sanityCheckValue","type":"uint256"},{"internalType":"bytes","name":"sanityCheckCallData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint16","name":"liquidationThresholdFinal","type":"uint16"},{"internalType":"uint40","name":"rampStart","type":"uint40"},{"internalType":"uint24","name":"rampDuration","type":"uint24"}],"name":"rampLiquidationThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newController","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"uint256","name":"debtLimit","type":"uint256"}],"name":"setCreditManagerDebtLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"uint40","name":"expirationDate","type":"uint40"}],"name":"setExpirationDate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"string","name":"group","type":"string"}],"name":"setGroup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint256","name":"lowerBound","type":"uint256"}],"name":"setLPPriceFeedLimiter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"uint128","name":"maxDebt","type":"uint128"}],"name":"setMaxDebtLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"uint8","name":"multiplier","type":"uint8"}],"name":"setMaxDebtPerBlockMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint16","name":"rate","type":"uint16"}],"name":"setMaxQuotaRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"uint128","name":"minDebt","type":"uint128"}],"name":"setMinDebtLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint16","name":"rate","type":"uint16"}],"name":"setMinQuotaRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"policyHash","type":"bytes32"},{"components":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint40","name":"delay","type":"uint40"},{"internalType":"uint8","name":"flags","type":"uint8"},{"internalType":"uint256","name":"exactValue","type":"uint256"},{"internalType":"uint256","name":"minValue","type":"uint256"},{"internalType":"uint256","name":"maxValue","type":"uint256"},{"internalType":"uint256","name":"referencePoint","type":"uint256"},{"internalType":"uint40","name":"referencePointUpdatePeriod","type":"uint40"},{"internalType":"uint40","name":"referencePointTimestampLU","type":"uint40"},{"internalType":"uint16","name":"minPctChangeDown","type":"uint16"},{"internalType":"uint16","name":"minPctChangeUp","type":"uint16"},{"internalType":"uint16","name":"maxPctChangeDown","type":"uint16"},{"internalType":"uint16","name":"maxPctChangeUp","type":"uint16"},{"internalType":"uint256","name":"minChange","type":"uint256"},{"internalType":"uint256","name":"maxChange","type":"uint256"}],"internalType":"struct Policy","name":"policyParams","type":"tuple"}],"name":"setPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"priceOracle","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"active","type":"bool"}],"name":"setReservePriceFeedStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint96","name":"limit","type":"uint96"}],"name":"setTokenLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint16","name":"quotaIncreaseFee","type":"uint16"}],"name":"setTokenQuotaIncreaseFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"newLimit","type":"uint256"}],"name":"setTotalDebtLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setVetoAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setWithdrawFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vetoAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040526000805461ff0019166101001790553480156200002057600080fd5b5060405162005426380380620054268339810160408190526200004391620001d6565b8180808062000052816200018e565b604051632bdad0e360e11b8152621050d360ea1b6004820152600060248201526001600160a01b038316906357b5a1c690604401602060405180830381865afa158015620000a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ca91906200020e565b6001600160a01b031660808190526000805460ff1916905560408051638da5cb5b60e01b81529051919350638da5cb5b92506004808201926020929091908290030181865afa15801562000122573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014891906200020e565b6000805462010000600160b01b031916620100006001600160a01b0393841602179055600380546001600160a01b03191694909116939093179092555062000233915050565b6001600160a01b038116620001b657604051635919af9760e11b815260040160405180910390fd5b50565b80516001600160a01b0381168114620001d157600080fd5b919050565b60008060408385031215620001ea57600080fd5b620001f583620001b9565b91506200020560208401620001b9565b90509250929050565b6000602082840312156200022157600080fd5b6200022c82620001b9565b9392505050565b6080516151c2620002646000396000818161081301528181613d9e01528181613e9e0152613f0a01526151c26000f3fe608060405234801561001057600080fd5b50600436106103155760003560e01c806379e4e3a9116101a7578063c091301c116100ee578063eadddb5011610097578063f9ed2b0a11610071578063f9ed2b0a146108ad578063fbae8b45146108c0578063fca595e3146108d357600080fd5b8063eadddb501461085a578063f2b065371461086d578063f77c47911461089457600080fd5b8063c9eea26c116100c8578063c9eea26c146107fb578063de2873591461080e578063ea26c4331461083557600080fd5b8063c091301c146107cb578063c1a287e2146107de578063c69ed5f2146107e857600080fd5b80638bf1695e1161015057806392eefe9b1161012a57806392eefe9b146105f5578063a3f685f914610608578063be236982146107b857600080fd5b80638bf1695e146105bc5780638ea08f97146105cf57806390f5100c146105e257600080fd5b80638456cb59116101815780638456cb591461058e57806387a64e071461059657806387f10c1d146105a957600080fd5b806379e4e3a91461053d5780637c37bb50146105505780637fd8067c1461057b57600080fd5b806354e0fb211161026b57806363d41698116102145780636e3d7997116101ee5780636e3d79971461050457806370ba333914610517578063778d70791461052a57600080fd5b806363d41698146104cb57806365ea307b146104de57806369ee991a146104f157600080fd5b806358d1ca6e1161024557806358d1ca6e1461048f5780635c975abb146104a25780635f24dbe8146104b857600080fd5b806354e0fb211461045257806354ecd6081461046557806354fd4d501461048657600080fd5b80633e7b9302116102cd57806344a0ab0f116102a757806344a0ab0f146103ef578063484b8e961461040257806353adce211461043257600080fd5b80633e7b9302146103c15780633f4ba83a146103d457806343ad71e1146103dc57600080fd5b80632a61e76c116102fe5780632a61e76c146103735780632b4fb6ad1461039957806333ccf633146103ae57600080fd5b80632522f8da1461031a578063280e56a414610348575b600080fd5b61032d610328366004613fb3565b6108e6565b60405164ffffffffff90911681526020015b60405180910390f35b61035b610356366004613fb3565b610950565b6040516001600160801b03909116815260200161033f565b610386610381366004613fd0565b6109bc565b60405161ffff909116815260200161033f565b6103ac6103a7366004614053565b610a37565b005b6103ac6103bc3660046140d9565b610cde565b6103ac6103cf366004613fb3565b610ed5565b6103ac610fd8565b6103ac6103ea36600461417a565b610fea565b6103ac6103fd3660046142c7565b61124f565b610415610410366004613fd0565b61142f565b6040516bffffffffffffffffffffffff909116815260200161033f565b610445610440366004613fb3565b6114ab565b60405161033f9190614362565b6103ac610460366004614375565b611557565b610478610473366004613fb3565b6116ca565b60405190815260200161033f565b61047861012c81565b61047861049d366004613fb3565b611738565b60005460ff16604051901515815260200161033f565b6103ac6104c63660046143a1565b61179c565b6103ac6104d93660046140d9565b6117f1565b6103ac6104ec366004614375565b6119e0565b6103ac6104ff3660046143ba565b611aef565b6103ac6105123660046143e8565b611e18565b6103ac6105253660046143a1565b611ef9565b61035b610538366004613fb3565b611f41565b6103ac61054b366004614375565b611fad565b600354610563906001600160a01b031681565b6040516001600160a01b03909116815260200161033f565b610386610589366004613fd0565b61212d565b6103ac6121aa565b6103ac6105a4366004614428565b6121ba565b6103ac6105b7366004613fd0565b612236565b6104786105ca366004613fb3565b61238d565b6103ac6105dd366004613fb3565b6123cd565b6103ac6105f0366004614375565b61244d565b6103ac610603366004613fb3565b612578565b6107ab6106163660046143a1565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081019190915250600090815260016020818152604092839020835161020081018552815460ff808216151583526101008083046001600160a01b031695840195909552600160a81b820464ffffffffff90811697840197909752600160d01b909104166060820152928101546080840152600281015460a0840152600381015460c0840152600481015460e08401526005810154808516928401929092526501000000000082049093166101208301526a0100000000000000000000810461ffff9081166101408401526c0100000000000000000000000082048116610160840152600160701b82048116610180840152600160801b909104166101a082015260068201546101c08201526007909101546101e082015290565b60405161033f91906144ad565b6104786107c6366004613fd0565b612603565b6103866107d9366004613fd0565b6126eb565b6104786212750081565b6103ac6107f63660046143a1565b612766565b610478610809366004613fd0565b612c65565b6105637f000000000000000000000000000000000000000000000000000000000000000081565b610848610843366004613fb3565b612cf3565b60405160ff909116815260200161033f565b6103ac6108683660046145af565b612d57565b61088061087b3660046143a1565b612f46565b60405161033f9897969594939291906145ef565b600054610563906201000090046001600160a01b031681565b6103ac6108bb3660046145af565b61313a565b6103ac6108ce3660046145af565b6132c3565b6103ac6108e136600461466e565b6134b2565b6000816001600160a01b0316638f6204876040518163ffffffff1660e01b8152600401602060405180830381865afa158015610926573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a919061469c565b92915050565b600080826001600160a01b031663166bf9d96040518163ffffffff1660e01b81526004016040805180830381865afa158015610990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b491906146b9565b949350505050565b6040516305b23b1160e11b81526001600160a01b0382811660048301526000918291851690630b64762290602401608060405180830381865afa158015610a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2b91906146e8565b50909695505050505050565b6001600160a01b038086166000908152600260209081526040808320938816835280832090519293610a6b939092016147fe565b60408051601f198184030181529082905280516020909101207f783274380000000000000000000000000000000000000000000000000000000082526001600160a01b03878116600484015290925060009190881690637832743890602401602060405180830381865afa158015610ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0b9190614862565b61ffff1690506000610b388360009081526001602052604090205464ffffffffff600160a81b9091041690565b9050610b4983838861ffff1661368a565b1580610b5c575062093a808462ffffff16105b80610b765750610b6c8142614895565b8564ffffffffff16105b15610b945760405163f06fc6e760e01b815260040160405180910390fd5b610cd3886001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf991906148a8565b6040518060600160405280603681526020016150e860369139604080516001600160a01b038c16602082015261ffff8b169181019190915264ffffffffff8916606082015262ffffff8816608082015260a00160405160208183030381529060405284610c668d8d612603565b6040516001600160a01b038f811660248301528e166044820152309063be236982906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506138f1565b505050505050505050565b6000826001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4291906148a8565b90506000836001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da891906148a8565b90506000610db582611f41565b9050610df5856040518060400160405280600881526020016713525397d111509560c21b815250836001600160801b0316876001600160801b0316613ae0565b610e125760405163f06fc6e760e01b815260040160405180910390fd5b610ecd836040518060400160405280601881526020017f7365744d696e446562744c696d69742875696e7431323829000000000000000081525086604051602001610e6c91906001600160801b0391909116815260200190565b60408051601f19818403018152828201909152600882526713525397d111509560c21b602083015290610ea0908a90613b39565b6040516001600160a01b03881660248201526001600160801b03871690309063778d707990604401610c8c565b505050505050565b610f17816040518060400160405280601581526020017f5550444154455f424f554e44535f414c4c4f5745440000000000000000000000815250600080613ae0565b610f345760405163f06fc6e760e01b815260040160405180910390fd5b610fd4816040518060400160405280601481526020017f666f72626964426f756e6473557064617465282900000000000000000000000081525060405180602001604052806000815250610fbd856040518060400160405280601581526020017f5550444154455f424f554e44535f414c4c4f5745440000000000000000000000815250613b39565b6000604051806020016040528060008152506138f1565b5050565b610fe0613ba0565b610fe8613bdf565b565b610ff2613c31565b60018082526000838152602082815260409182902084518154838701518588015160608901517fffffffffffffffffffffff0000000000000000000000000000000000000000009093169315157fffffffffffffffffffffff0000000000000000000000000000000000000000ff16939093176101006001600160a01b039092168202177fffffffffff000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b64ffffffffff948516027fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff1617600160d01b60ff9093169290920291909117835560808701518387015560a0870151600284015560c0870151600384015560e087015160048401558601516005830180546101208901516101408a01516101608b01516101808c01516101a08d015196881669ffffffffffffffffffff1990951694909417650100000000009390971692909202959095176dffffffff0000000000000000000019166a010000000000000000000061ffff968716026dffff0000000000000000000000001916176c0100000000000000000000000091861691909102177fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff16600160701b918516919091027fffffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffff1617600160801b93909216929092021790556101c085015160068201556101e0850151600790910155905191825283917fe7d3ad39af384f74aa98471d169bf505294494fe423d16402df3ce2a37584314910160405180910390a25050565b6001600160a01b038084166000908152600260209081526040808320938616835280832090519293611283939092016148c5565b6040516020818303038152906040528051906020012090506000846001600160a01b031663be8da14b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ff91906148a8565b9050600061130d828661142f565b905061133683826bffffffffffffffffffffffff16866bffffffffffffffffffffffff1661368a565b6113535760405163f06fc6e760e01b815260040160405180910390fd5b611426826040518060400160405280601d81526020017f736574546f6b656e4c696d697428616464726573732c75696e7439362900000081525087876040516020016113c29291906001600160a01b039290921682526bffffffffffffffffffffffff16602082015260400190565b60408051601f19818403018152918152600088815260016020522054600160a81b900464ffffffffff166040516001600160a01b0388811660248301528b1660448201526bffffffffffffffffffffffff871690309063484b8e9690606401610c8c565b50505050505050565b60405163bd42a06f60e01b81526001600160a01b038281166004830152600091829185169063bd42a06f9060240160c060405180830381865afa15801561147a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149e9190614929565b5098975050505050505050565b6001600160a01b03811660009081526002602052604090208054606091906114d290614747565b80601f01602080910402602001604051908101604052809291908181526020018280546114fe90614747565b801561154b5780601f106115205761010080835404028352916020019161154b565b820191906000526020600020905b81548152906001019060200180831161152e57829003601f168201915b50505050509050919050565b6001600160a01b0382166000908152600260209081526040808320905161157e92016149cd565b6040516020818303038152906040528051906020012090506000836001600160a01b031663e941fa786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fa9190614862565b61ffff16905061160b82828561368a565b6116285760405163f06fc6e760e01b815260040160405180910390fd5b6116c3846040518060400160405280601781526020017f73657457697468647261774665652875696e74323536290000000000000000008152508560405160200161167591815260200190565b60408051601f19818403018152918152600087815260016020522054600160a81b900464ffffffffff166040516001600160a01b038a166024820152869030906354ecd60890604401610c8c565b5050505050565b6000816001600160a01b031663e941fa786040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190614862565b61ffff1692915050565b6000816001600160a01b031663183ace906040518163ffffffff1660e01b8152600401602060405180830381865afa158015611778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a9190614a1f565b6117a4613c31565b6000818152600160209081526040808320805460ff191690555191825282917fe7d3ad39af384f74aa98471d169bf505294494fe423d16402df3ce2a37584314910160405180910390a250565b6000826001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611831573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185591906148a8565b90506000836001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bb91906148a8565b905060006118c882610950565b9050611908856040518060400160405280600881526020016713505617d111509560c21b815250836001600160801b0316876001600160801b0316613ae0565b6119255760405163f06fc6e760e01b815260040160405180910390fd5b610ecd836040518060400160405280601881526020017f7365744d6178446562744c696d69742875696e743132382900000000000000008152508660405160200161197f91906001600160801b0391909116815260200190565b60408051601f19818403018152828201909152600882526713505617d111509560c21b6020830152906119b3908a90613b39565b6040516001600160a01b03881660248201526001600160801b03871690309063280e56a490604401610c8c565b6001600160a01b03821660009081526002602090815260408083209051611a079201614a38565b6040516020818303038152906040528051906020012090506000611a2a84611738565b9050611a3782828561368a565b611a545760405163f06fc6e760e01b815260040160405180910390fd5b6116c3846040518060400160405280601a81526020017f736574546f74616c446562744c696d69742875696e743235362900000000000081525085604051602001611aa191815260200190565b60408051601f19818403018152918152600087815260016020522054600160a81b900464ffffffffff166040516001600160a01b038a166024820152869030906358d1ca6e90604401610c8c565b6000826001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5391906148a8565b90506000836001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb991906148a8565b90506000846001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1f91906148a8565b90506000611c2c826108e6565b9050611c7d866040518060400160405280600f81526020017f45585049524154494f4e5f4441544500000000000000000000000000000000008152508364ffffffffff168864ffffffffff16613ae0565b611c9a5760405163f06fc6e760e01b815260040160405180910390fd5b6040517f7a99c0170000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009190851690637a99c01790602401602060405180830381865afa158015611cfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d219190614a1f565b90508015611d425760405163f06fc6e760e01b815260040160405180910390fd5b611e0e856040518060400160405280601981526020017f73657445787069726174696f6e446174652875696e743430290000000000000081525088604051602001611d9a919064ffffffffff91909116815260200190565b60408051601f19818403018152828201909152600f82527f45585049524154494f4e5f444154450000000000000000000000000000000000602083015290611de3908c90613b39565b6040516001600160a01b038916602482015264ffffffffff8816903090632522f8da90604401610c8c565b5050505050505050565b6001600160a01b038084166000908152600260209081526040808320938616835280832090519293611e4c93909201614a8a565b604051602081830303815290604052805190602001209050611e708160008061368a565b611e8d5760405163f06fc6e760e01b815260040160405180910390fd5b6116c38460405180606001604052806027815260200161509f60279139604080516001600160a01b03881660208201528615159181019190915260600160408051601f19818403018152918152600086815260016020522054600160a81b900464ffffffffff16610fbd565b611f01613c70565b600081815260046020526040808220805460ff191690555182917fbb8e18922d3abb7d8aea19f1b55d85b0ee985798c196aad6d05c58dfdb7c98af91a250565b600080826001600160a01b031663166bf9d96040518163ffffffff1660e01b81526004016040805180830381865afa158015611f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa591906146b9565b509392505050565b6000826001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201191906148a8565b9050600061201f8285612c65565b9050612062846040518060400160405280601981526020017f4352454449545f4d414e414745525f444542545f4c494d4954000000000000008152508386613ae0565b61207f5760405163f06fc6e760e01b815260040160405180910390fd5b6116c3826040518060600160405280602a815260200161511e602a9139604080516001600160a01b038916602082015290810187905260600160408051601f19818403018152828201909152601982527f4352454449545f4d414e414745525f444542545f4c494d495400000000000000602083015290612101908990613b39565b6040516001600160a01b0388811660248301528a1660448201528690309063c9eea26c90606401610c8c565b60405163bd42a06f60e01b81526001600160a01b038281166004830152600091829185169063bd42a06f9060240160c060405180830381865afa158015612178573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219c9190614929565b509198975050505050505050565b6121b2613cb4565b610fe8613cf3565b6121c2613c31565b6001600160a01b03831660009081526002602052604090206121e5828483614b39565b5081816040516121f6929190614bf9565b604051908190038120906001600160a01b038516907f92862d5b730cd2540433b48d4973472ba23dcd95d056d22098ebc8ac3d6c741d90600090a3505050565b6001600160a01b0382166000908152600260209081526040808320905161225d9201614c09565b6040516020818303038152906040528051906020012090506000836001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d991906148a8565b90506122e78260008061368a565b6123045760405163f06fc6e760e01b815260040160405180910390fd5b6116c3816040518060400160405280601681526020017f666f7262696441646170746572286164647265737329000000000000000000008152508560405160200161235e91906001600160a01b0391909116815260200190565b60408051601f19818403018152918152600087815260016020522054600160a81b900464ffffffffff16610fbd565b6000816001600160a01b031663a384d6ff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611778573d6000803e3d6000fd5b6123d5613c31565b6003546001600160a01b0382811691161461244a57600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f186cb628766b6429a759e2bca5d79296f60bfb05a03df1f892e5fba8b03be33590600090a25b50565b60006124588361238d565b905061249b836040518060400160405280601581526020017f4c505f50524943455f464545445f4c494d4954455200000000000000000000008152508385613ae0565b6124b85760405163f06fc6e760e01b815260040160405180910390fd5b612572836040518060400160405280601381526020017f7365744c696d697465722875696e7432353629000000000000000000000000008152508460405160200161250591815260200190565b60408051601f19818403018152828201909152601582527f4c505f50524943455f464545445f4c494d49544552000000000000000000000060208301529061254e908890613b39565b6040516001600160a01b038916602482015286903090638bf1695e90604401610c8c565b50505050565b612580613c31565b6000546001600160a01b0382811662010000909204161461244a57600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff16620100006001600160a01b03841690810291909117825560405190917fe253457d9ad994ca9682fc3bbc38c890dca73a2d5ecee3809e548bac8b00d7c691a250565b6040517f3201de4c0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152600091829182918291829190881690633201de4c90602401608060405180830381865afa15801561266e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126929190614c5b565b6040805161ffff958616602080830191909152949095168582015264ffffffffff92909216606085015262ffffff166080808501919091528151808503909101815260a090930190528151910120979650505050505050565b6040516305b23b1160e11b81526001600160a01b0382811660048301526000918291851690630b64762290602401608060405180830381865afa158015612736573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275a91906146e8565b50919695505050505050565b600081815260046020908152604080832081516101008082018452825460ff811615158352046001600160a01b0390811694820194909452600182015493841692810192909252600160a01b90920464ffffffffff1660608201526002820180549192916080840191906127d990614747565b80601f016020809104026020016040519081016040528092919081815260200182805461280590614747565b80156128525780601f1061282757610100808354040283529160200191612852565b820191906000526020600020905b81548152906001019060200180831161283557829003601f168201915b5050505050815260200160038201805461286b90614747565b80601f016020809104026020016040519081016040528092919081815260200182805461289790614747565b80156128e45780601f106128b9576101008083540402835291602001916128e4565b820191906000526020600020905b8154815290600101906020018083116128c757829003601f168201915b505050505081526020016004820154815260200160058201805461290790614747565b80601f016020809104026020016040519081016040528092919081815260200182805461293390614747565b80156129805780601f1061295557610100808354040283529160200191612980565b820191906000526020600020905b81548152906001019060200180831161296357829003601f168201915b505050505081525050905080600001516129c6576040517f47a157cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80602001516001600160a01b0316336001600160a01b031614612a15576040517f737d8ae200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408101516060820151608083015160a084015164ffffffffff8316421080612a505750612a4d6212750064ffffffffff8516614895565b42115b15612a87576040517f564de7fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60e08501515115612b46576000306001600160a01b03168660e00151604051612ab09190614caf565b600060405180830381855afa9150503d8060008114612aeb576040519150601f19603f3d011682016040523d82523d6000602084013e612af0565b606091505b509150508560c0015181806020019051810190612b0d9190614a1f565b14612b44576040517f0a5f425900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b6000868152600460205260408120805460ff19169055825160609103612b6d575080612b99565b828051906020012082604051602001612b87929190614ccb565b60405160208183030381529060405290505b6000856001600160a01b031682604051612bb39190614caf565b6000604051808303816000865af19150503d8060008114612bf0576040519150601f19603f3d011682016040523d82523d6000602084013e612bf5565b606091505b5050905080612c30576040517fdc3f6c3300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405188907fef9d8cdf871686f540056b412c18c767afeb6ec3fe4040634ad43b192643103a90600090a25050505050505050565b6040517fb0df2c660000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000919084169063b0df2c6690602401602060405180830381865afa158015612cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cec9190614a1f565b9392505050565b6000816001600160a01b031663478ade366040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d33573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a9190614d13565b6001600160a01b038084166000908152600260209081526040808320938616835280832090519293612d8b93909201614d30565b6040516020818303038152906040528051906020012090506000846001600160a01b031663be8da14b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0791906148a8565b90506000816001600160a01b031663a6f19c846040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6d91906148a8565b90506000612e7b82876109bc565b9050612e90848261ffff168761ffff1661368a565b612ead5760405163f06fc6e760e01b815260040160405180910390fd5b611e0e826040518060600160405280602281526020016150c660229139604080516001600160a01b038b16602082015261ffff8a169181019190915260600160408051601f19818403018152918152600089815260016020522054600160a81b900464ffffffffff166040516001600160a01b0388811660248301528c16604482015261ffff8716903090632a61e76c90606401610c8c565b60046020526000908152604090208054600182015460028301805460ff8416946001600160a01b0361010090950485169484169364ffffffffff600160a01b90910416929091612f9590614747565b80601f0160208091040260200160405190810160405280929190818152602001828054612fc190614747565b801561300e5780601f10612fe35761010080835404028352916020019161300e565b820191906000526020600020905b815481529060010190602001808311612ff157829003601f168201915b50505050509080600301805461302390614747565b80601f016020809104026020016040519081016040528092919081815260200182805461304f90614747565b801561309c5780601f106130715761010080835404028352916020019161309c565b820191906000526020600020905b81548152906001019060200180831161307f57829003601f168201915b5050505050908060040154908060050180546130b790614747565b80601f01602080910402602001604051908101604052809291908181526020018280546130e390614747565b80156131305780601f1061310557610100808354040283529160200191613130565b820191906000526020600020905b81548152906001019060200180831161311357829003601f168201915b5050505050905088565b6001600160a01b03808416600090815260026020908152604080832093861683528083209051929361316e93909201614d94565b6040516020818303038152906040528051906020012090506000846001600160a01b031663be8da14b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ea91906148a8565b905060006131f8828661212d565b905061320d838261ffff168661ffff1661368a565b61322a5760405163f06fc6e760e01b815260040160405180910390fd5b6114268260405180606001604052806028815260200161507760289139604080516001600160a01b038a16602082015261ffff89169181019190915260600160408051601f19818403018152918152600088815260016020522054600160a81b900464ffffffffff166040516001600160a01b0388811660248301528b16604482015261ffff8716903090637fd8067c90606401610c8c565b6001600160a01b0380841660009081526002602090815260408083209386168352808320905192936132f793909201614df8565b6040516020818303038152906040528051906020012090506000846001600160a01b031663be8da14b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561334f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061337391906148a8565b90506000816001600160a01b031663a6f19c846040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133d991906148a8565b905060006133e782876126eb565b90506133fc848261ffff168761ffff1661368a565b6134195760405163f06fc6e760e01b815260040160405180910390fd5b611e0e8260405180606001604052806022815260200161514860229139604080516001600160a01b038b16602082015261ffff8a169181019190915260600160408051601f19818403018152918152600089815260016020522054600160a81b900464ffffffffff166040516001600160a01b0388811660248301528c16604482015261ffff871690309063c091301c90606401610c8c565b6000826001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351691906148a8565b90506000836001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015613558573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357c91906148a8565b9050600061358982612cf3565b90506135d2856040518060400160405280601d81526020017f4d41585f444542545f5045525f424c4f434b5f4d554c5449504c4945520000008152508360ff168760ff16613ae0565b6135ef5760405163f06fc6e760e01b815260040160405180910390fd5b610ecd8360405180606001604052806023815260200161516a602391396040805160ff891660208201520160408051601f19818403018152828201909152601d82527f4d41585f444542545f5045525f424c4f434b5f4d554c5449504c494552000000602083015290613663908a90613b39565b6040516001600160a01b038816602482015260ff871690309063ea26c43390604401610c8c565b6000838152600160205260408120805460ff166136ab576000915050612cec565b805461010090046001600160a01b031633146136cb576000915050612cec565b8054600160d01b900460ff811690600116156136f757816001015484146136f757600092505050612cec565b600281161561371757816002015484101561371757600092505050612cec565b600481161561373757816003015484111561373757600092505050612cec565b600060788216156138e45760058301546137649064ffffffffff8082169165010000000000900416614e5c565b64ffffffffff164211156137a657506004820185905560058201805469ffffffffff00000000001916650100000000004264ffffffffff1602179055846137ad565b5060048201545b6000806137ba8784613d30565b909250905060088416156137e25784600601548210156137e257600095505050505050612cec565b601084161561380557846007015482111561380557600095505050505050612cec565b60608416156138e15760008361381d61271085614e81565b6138279190614e98565b905060208516158015906138785750816138575760058601546a0100000000000000000000900461ffff16613871565b60058601546c01000000000000000000000000900461ffff165b61ffff1681105b1561388c5760009650505050505050612cec565b60408516158015906138cb5750816138b3576005860154600160701b900461ffff166138c4565b6005860154600160801b900461ffff165b61ffff1681115b156138df5760009650505050505050612cec565b505b50505b5060019695505050505050565b6000806138fe8542614895565b90506000338989898560405160200161391b959493929190614eba565b604051602081830303815290604052805190602001209050604051806101000160405280600115158152602001336001600160a01b031681526020018a6001600160a01b031681526020018364ffffffffff168152602001898152602001888152602001868152602001858152506004600083815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160010160146101000a81548164ffffffffff021916908364ffffffffff1602179055506080820151816002019081613a549190614f0b565b5060a08201516003820190613a699082614f0b565b5060c0820151600482015560e08201516005820190613a889082614f0b565b50905050336001600160a01b0316817fcbc0420b9ccad04c18c723bfad07db88131bc78c76ca44827afdd7784d3ddfe28b8b8b87604051613acc9493929190614fcb565b60405180910390a398975050505050505050565b6001600160a01b038416600090815260026020908152604080832090518392613b0c9291889101615018565b604051602081830303815290604052805190602001209050613b2f81858561368a565b9695505050505050565b6001600160a01b038216600090815260026020908152604080832090518392613b659291869101615018565b60408051808303601f19018152918152815160209283012060009081526001909252902054600160a81b900464ffffffffff16949350505050565b613ba933613d63565b610fe8576040517f16e29ab700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613be7613e0c565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b613c3a33613e63565b610fe8576040517f61081c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003546001600160a01b03163314610fe8576040517f349beb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613cbd33613ecf565b610fe8576040517fd794b1e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613cfb613f3b565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613c143390565b600080828411613d4b57613d448484615046565b6000613d58565b613d558385615046565b60015b915091509250929050565b6040517fd4eb5db00000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063d4eb5db0906024015b602060405180830381865afa158015613de8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a9190615059565b60005460ff16610fe85760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064015b60405180910390fd5b6040517f5f259aba0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690635f259aba90602401613dcb565b6040517f3a41ec640000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000000000000000000000000000000000000000000090911690633a41ec6490602401613dcb565b60005460ff1615610fe85760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401613e5a565b6001600160a01b038116811461244a57600080fd5b8035613fae81613f8e565b919050565b600060208284031215613fc557600080fd5b8135612cec81613f8e565b60008060408385031215613fe357600080fd5b8235613fee81613f8e565b91506020830135613ffe81613f8e565b809150509250929050565b61ffff8116811461244a57600080fd5b8035613fae81614009565b64ffffffffff8116811461244a57600080fd5b8035613fae81614024565b62ffffff8116811461244a57600080fd5b600080600080600060a0868803121561406b57600080fd5b853561407681613f8e565b9450602086013561408681613f8e565b9350604086013561409681614009565b925060608601356140a681614024565b915060808601356140b681614042565b809150509295509295909350565b6001600160801b038116811461244a57600080fd5b600080604083850312156140ec57600080fd5b82356140f781613f8e565b91506020830135613ffe816140c4565b634e487b7160e01b600052604160045260246000fd5b604051610200810167ffffffffffffffff8111828210171561414157614141614107565b60405290565b801515811461244a57600080fd5b8035613fae81614147565b60ff8116811461244a57600080fd5b8035613fae81614160565b60008082840361022081121561418f57600080fd5b8335925061020080601f19830112156141a757600080fd5b6141af61411d565b91506141bd60208601614155565b82526141cb60408601613fa3565b60208301526141dc60608601614037565b60408301526141ed6080860161416f565b606083015260a0850135608083015260c085013560a083015260e085013560c08301526101008086013560e084015261012061422a818801614037565b82850152610140915061423e828801614037565b90840152610160614250878201614019565b828501526101809150614264828801614019565b908401526101a0614276878201614019565b828501526101c0915061428a828801614019565b908401526101e08681013591840191909152940135938101939093525092909150565b6bffffffffffffffffffffffff8116811461244a57600080fd5b6000806000606084860312156142dc57600080fd5b83356142e781613f8e565b925060208401356142f781613f8e565b91506040840135614307816142ad565b809150509250925092565b60005b8381101561432d578181015183820152602001614315565b50506000910152565b6000815180845261434e816020860160208601614312565b601f01601f19169290920160200192915050565b602081526000612cec6020830184614336565b6000806040838503121561438857600080fd5b823561439381613f8e565b946020939093013593505050565b6000602082840312156143b357600080fd5b5035919050565b600080604083850312156143cd57600080fd5b82356143d881613f8e565b91506020830135613ffe81614024565b6000806000606084860312156143fd57600080fd5b833561440881613f8e565b9250602084013561441881613f8e565b9150604084013561430781614147565b60008060006040848603121561443d57600080fd5b833561444881613f8e565b9250602084013567ffffffffffffffff8082111561446557600080fd5b818601915086601f83011261447957600080fd5b81358181111561448857600080fd5b87602082850101111561449a57600080fd5b6020830194508093505050509250925092565b815115158152610200810160208301516144d260208401826001600160a01b03169052565b5060408301516144eb604084018264ffffffffff169052565b506060830151614500606084018260ff169052565b506080830151608083015260a083015160a083015260c083015160c083015260e083015160e0830152610100808401516145428285018264ffffffffff169052565b50506101208381015164ffffffffff16908301526101408084015161ffff9081169184019190915261016080850151821690840152610180808501518216908401526101a080850151909116908301526101c080840151908301526101e092830151929091019190915290565b6000806000606084860312156145c457600080fd5b83356145cf81613f8e565b925060208401356145df81613f8e565b9150604084013561430781614009565b60006101008a151583526001600160a01b03808b166020850152808a1660408501525064ffffffffff8816606084015280608084015261463181840188614336565b905082810360a08401526146458187614336565b90508460c084015282810360e084015261465f8185614336565b9b9a5050505050505050505050565b6000806040838503121561468157600080fd5b823561468c81613f8e565b91506020830135613ffe81614160565b6000602082840312156146ae57600080fd5b8151612cec81614024565b600080604083850312156146cc57600080fd5b82516146d7816140c4565b6020840151909250613ffe816140c4565b600080600080608085870312156146fe57600080fd5b845161470981614009565b602086015190945061471a81614009565b604086015190935061472b816142ad565b606086015190925061473c816142ad565b939692955090935050565b600181811c9082168061475b57607f821691505b60208210810361477b57634e487b7160e01b600052602260045260246000fd5b50919050565b6000815461478e81614747565b8085526020600183811680156147ab57600181146147c5576147f3565b60ff1985168884015283151560051b8801830195506147f3565b866000528260002060005b858110156147eb5781548a82018601529083019084016147d0565b890184019650505b505050505092915050565b6060815260006148116060830185614781565b82810360208401526148238185614781565b838103604094850152600881527f544f4b454e5f4c54000000000000000000000000000000000000000000000000602082015292909201949350505050565b60006020828403121561487457600080fd5b8151612cec81614009565b634e487b7160e01b600052601160045260246000fd5b8082018082111561094a5761094a61487f565b6000602082840312156148ba57600080fd5b8151612cec81613f8e565b6060815260006148d86060830185614781565b82810360208401526148ea8185614781565b838103604094850152600b81527f544f4b454e5f4c494d4954000000000000000000000000000000000000000000602082015292909201949350505050565b60008060008060008060c0878903121561494257600080fd5b865161494d81614009565b602088015190965077ffffffffffffffffffffffffffffffffffffffffffffffff8116811461497b57600080fd5b604088015190955061498c81614009565b606088015190945061499d816142ad565b60808801519093506149ae816142ad565b60a08801519092506149bf81614147565b809150509295509295509295565b6040815260006149e06040830184614781565b8281036020840152600c81527f57495448445241575f464545000000000000000000000000000000000000000060208201526040810191505092915050565b600060208284031215614a3157600080fd5b5051919050565b604081526000614a4b6040830184614781565b8281036020840152601081527f544f54414c5f444542545f4c494d49540000000000000000000000000000000060208201526040810191505092915050565b606081526000614a9d6060830185614781565b8281036020840152614aaf8185614781565b838103604094850152601981527f524553455256455f50524943455f464545445f53544154555300000000000000602082015292909201949350505050565b601f821115614b3457600081815260208120601f850160051c81016020861015614b155750805b601f850160051c820191505b81811015610ecd57828155600101614b21565b505050565b67ffffffffffffffff831115614b5157614b51614107565b614b6583614b5f8354614747565b83614aee565b6000601f841160018114614b995760008515614b815750838201355b600019600387901b1c1916600186901b1783556116c3565b600083815260209020601f19861690835b82811015614bca5786850135825560209485019460019092019101614baa565b5086821015614be75760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8183823760009101908152919050565b604081526000614c1c6040830184614781565b8281036020840152600e81527f464f524249445f4144415054455200000000000000000000000000000000000060208201526040810191505092915050565b60008060008060808587031215614c7157600080fd5b8451614c7c81614009565b6020860151909450614c8d81614009565b6040860151909350614c9e81614024565b606086015190925061473c81614042565b60008251614cc1818460208701614312565b9190910192915050565b7fffffffff000000000000000000000000000000000000000000000000000000008316815260008251614d05816004850160208701614312565b919091016004019392505050565b600060208284031215614d2557600080fd5b8151612cec81614160565b606081526000614d436060830185614781565b8281036020840152614d558185614781565b838103604094850152601481527f544f4b454e5f51554f54415f4d41585f52415445000000000000000000000000602082015292909201949350505050565b606081526000614da76060830185614781565b8281036020840152614db98185614781565b838103604094850152601881527f544f4b454e5f51554f54415f494e4352454153455f4645450000000000000000602082015292909201949350505050565b606081526000614e0b6060830185614781565b8281036020840152614e1d8185614781565b838103604094850152601481527f544f4b454e5f51554f54415f4d494e5f52415445000000000000000000000000602082015292909201949350505050565b64ffffffffff818116838216019080821115614e7a57614e7a61487f565b5092915050565b808202811582820484141761094a5761094a61487f565b600082614eb557634e487b7160e01b600052601260045260246000fd5b500490565b60006001600160a01b03808816835280871660208401525060a06040830152614ee660a0830186614336565b8281036060840152614ef88186614336565b9150508260808301529695505050505050565b815167ffffffffffffffff811115614f2557614f25614107565b614f3981614f338454614747565b84614aee565b602080601f831160018114614f6e5760008415614f565750858301515b600019600386901b1c1916600185901b178555610ecd565b600085815260208120601f198616915b82811015614f9d57888601518255948401946001909101908401614f7e565b5085821015614fbb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385168152608060208201526000614fed6080830186614336565b8281036040840152614fff8186614336565b91505064ffffffffff8316606083015295945050505050565b60408152600061502b6040830185614781565b828103602084015261503d8185614336565b95945050505050565b8181038181111561094a5761094a61487f565b60006020828403121561506b57600080fd5b8151612cec8161414756fe736574546f6b656e51756f7461496e63726561736546656528616464726573732c75696e743136297365745265736572766550726963654665656453746174757328616464726573732c626f6f6c296368616e676551756f74614d61785261746528616464726573732c75696e7431362972616d704c69717569646174696f6e5468726573686f6c6428616464726573732c75696e7431362c75696e7434302c75696e743234297365744372656469744d616e61676572446562744c696d697428616464726573732c75696e74323536296368616e676551756f74614d696e5261746528616464726573732c75696e743136297365744d617844656274506572426c6f636b4d756c7469706c6965722875696e743829a26469706673582212208401e7290eef9f3ddd3f43d43ded6aa00f0dea65b02e5292c0cb90cbd613b3a964736f6c634300081100330000000000000000000000004b27b296273b72d7c7bfee1ace93dc081467c41b000000000000000000000000393ec629b90389f957c5a2e4fc2f8f488e735bfc
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103155760003560e01c806379e4e3a9116101a7578063c091301c116100ee578063eadddb5011610097578063f9ed2b0a11610071578063f9ed2b0a146108ad578063fbae8b45146108c0578063fca595e3146108d357600080fd5b8063eadddb501461085a578063f2b065371461086d578063f77c47911461089457600080fd5b8063c9eea26c116100c8578063c9eea26c146107fb578063de2873591461080e578063ea26c4331461083557600080fd5b8063c091301c146107cb578063c1a287e2146107de578063c69ed5f2146107e857600080fd5b80638bf1695e1161015057806392eefe9b1161012a57806392eefe9b146105f5578063a3f685f914610608578063be236982146107b857600080fd5b80638bf1695e146105bc5780638ea08f97146105cf57806390f5100c146105e257600080fd5b80638456cb59116101815780638456cb591461058e57806387a64e071461059657806387f10c1d146105a957600080fd5b806379e4e3a91461053d5780637c37bb50146105505780637fd8067c1461057b57600080fd5b806354e0fb211161026b57806363d41698116102145780636e3d7997116101ee5780636e3d79971461050457806370ba333914610517578063778d70791461052a57600080fd5b806363d41698146104cb57806365ea307b146104de57806369ee991a146104f157600080fd5b806358d1ca6e1161024557806358d1ca6e1461048f5780635c975abb146104a25780635f24dbe8146104b857600080fd5b806354e0fb211461045257806354ecd6081461046557806354fd4d501461048657600080fd5b80633e7b9302116102cd57806344a0ab0f116102a757806344a0ab0f146103ef578063484b8e961461040257806353adce211461043257600080fd5b80633e7b9302146103c15780633f4ba83a146103d457806343ad71e1146103dc57600080fd5b80632a61e76c116102fe5780632a61e76c146103735780632b4fb6ad1461039957806333ccf633146103ae57600080fd5b80632522f8da1461031a578063280e56a414610348575b600080fd5b61032d610328366004613fb3565b6108e6565b60405164ffffffffff90911681526020015b60405180910390f35b61035b610356366004613fb3565b610950565b6040516001600160801b03909116815260200161033f565b610386610381366004613fd0565b6109bc565b60405161ffff909116815260200161033f565b6103ac6103a7366004614053565b610a37565b005b6103ac6103bc3660046140d9565b610cde565b6103ac6103cf366004613fb3565b610ed5565b6103ac610fd8565b6103ac6103ea36600461417a565b610fea565b6103ac6103fd3660046142c7565b61124f565b610415610410366004613fd0565b61142f565b6040516bffffffffffffffffffffffff909116815260200161033f565b610445610440366004613fb3565b6114ab565b60405161033f9190614362565b6103ac610460366004614375565b611557565b610478610473366004613fb3565b6116ca565b60405190815260200161033f565b61047861012c81565b61047861049d366004613fb3565b611738565b60005460ff16604051901515815260200161033f565b6103ac6104c63660046143a1565b61179c565b6103ac6104d93660046140d9565b6117f1565b6103ac6104ec366004614375565b6119e0565b6103ac6104ff3660046143ba565b611aef565b6103ac6105123660046143e8565b611e18565b6103ac6105253660046143a1565b611ef9565b61035b610538366004613fb3565b611f41565b6103ac61054b366004614375565b611fad565b600354610563906001600160a01b031681565b6040516001600160a01b03909116815260200161033f565b610386610589366004613fd0565b61212d565b6103ac6121aa565b6103ac6105a4366004614428565b6121ba565b6103ac6105b7366004613fd0565b612236565b6104786105ca366004613fb3565b61238d565b6103ac6105dd366004613fb3565b6123cd565b6103ac6105f0366004614375565b61244d565b6103ac610603366004613fb3565b612578565b6107ab6106163660046143a1565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081019190915250600090815260016020818152604092839020835161020081018552815460ff808216151583526101008083046001600160a01b031695840195909552600160a81b820464ffffffffff90811697840197909752600160d01b909104166060820152928101546080840152600281015460a0840152600381015460c0840152600481015460e08401526005810154808516928401929092526501000000000082049093166101208301526a0100000000000000000000810461ffff9081166101408401526c0100000000000000000000000082048116610160840152600160701b82048116610180840152600160801b909104166101a082015260068201546101c08201526007909101546101e082015290565b60405161033f91906144ad565b6104786107c6366004613fd0565b612603565b6103866107d9366004613fd0565b6126eb565b6104786212750081565b6103ac6107f63660046143a1565b612766565b610478610809366004613fd0565b612c65565b6105637f000000000000000000000000ad131da4bddb40ebb5ceeaea87067553d431389581565b610848610843366004613fb3565b612cf3565b60405160ff909116815260200161033f565b6103ac6108683660046145af565b612d57565b61088061087b3660046143a1565b612f46565b60405161033f9897969594939291906145ef565b600054610563906201000090046001600160a01b031681565b6103ac6108bb3660046145af565b61313a565b6103ac6108ce3660046145af565b6132c3565b6103ac6108e136600461466e565b6134b2565b6000816001600160a01b0316638f6204876040518163ffffffff1660e01b8152600401602060405180830381865afa158015610926573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a919061469c565b92915050565b600080826001600160a01b031663166bf9d96040518163ffffffff1660e01b81526004016040805180830381865afa158015610990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b491906146b9565b949350505050565b6040516305b23b1160e11b81526001600160a01b0382811660048301526000918291851690630b64762290602401608060405180830381865afa158015610a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a2b91906146e8565b50909695505050505050565b6001600160a01b038086166000908152600260209081526040808320938816835280832090519293610a6b939092016147fe565b60408051601f198184030181529082905280516020909101207f783274380000000000000000000000000000000000000000000000000000000082526001600160a01b03878116600484015290925060009190881690637832743890602401602060405180830381865afa158015610ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0b9190614862565b61ffff1690506000610b388360009081526001602052604090205464ffffffffff600160a81b9091041690565b9050610b4983838861ffff1661368a565b1580610b5c575062093a808462ffffff16105b80610b765750610b6c8142614895565b8564ffffffffff16105b15610b945760405163f06fc6e760e01b815260040160405180910390fd5b610cd3886001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf991906148a8565b6040518060600160405280603681526020016150e860369139604080516001600160a01b038c16602082015261ffff8b169181019190915264ffffffffff8916606082015262ffffff8816608082015260a00160405160208183030381529060405284610c668d8d612603565b6040516001600160a01b038f811660248301528e166044820152309063be236982906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506138f1565b505050505050505050565b6000826001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4291906148a8565b90506000836001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da891906148a8565b90506000610db582611f41565b9050610df5856040518060400160405280600881526020016713525397d111509560c21b815250836001600160801b0316876001600160801b0316613ae0565b610e125760405163f06fc6e760e01b815260040160405180910390fd5b610ecd836040518060400160405280601881526020017f7365744d696e446562744c696d69742875696e7431323829000000000000000081525086604051602001610e6c91906001600160801b0391909116815260200190565b60408051601f19818403018152828201909152600882526713525397d111509560c21b602083015290610ea0908a90613b39565b6040516001600160a01b03881660248201526001600160801b03871690309063778d707990604401610c8c565b505050505050565b610f17816040518060400160405280601581526020017f5550444154455f424f554e44535f414c4c4f5745440000000000000000000000815250600080613ae0565b610f345760405163f06fc6e760e01b815260040160405180910390fd5b610fd4816040518060400160405280601481526020017f666f72626964426f756e6473557064617465282900000000000000000000000081525060405180602001604052806000815250610fbd856040518060400160405280601581526020017f5550444154455f424f554e44535f414c4c4f5745440000000000000000000000815250613b39565b6000604051806020016040528060008152506138f1565b5050565b610fe0613ba0565b610fe8613bdf565b565b610ff2613c31565b60018082526000838152602082815260409182902084518154838701518588015160608901517fffffffffffffffffffffff0000000000000000000000000000000000000000009093169315157fffffffffffffffffffffff0000000000000000000000000000000000000000ff16939093176101006001600160a01b039092168202177fffffffffff000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b64ffffffffff948516027fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff1617600160d01b60ff9093169290920291909117835560808701518387015560a0870151600284015560c0870151600384015560e087015160048401558601516005830180546101208901516101408a01516101608b01516101808c01516101a08d015196881669ffffffffffffffffffff1990951694909417650100000000009390971692909202959095176dffffffff0000000000000000000019166a010000000000000000000061ffff968716026dffff0000000000000000000000001916176c0100000000000000000000000091861691909102177fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff16600160701b918516919091027fffffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffff1617600160801b93909216929092021790556101c085015160068201556101e0850151600790910155905191825283917fe7d3ad39af384f74aa98471d169bf505294494fe423d16402df3ce2a37584314910160405180910390a25050565b6001600160a01b038084166000908152600260209081526040808320938616835280832090519293611283939092016148c5565b6040516020818303038152906040528051906020012090506000846001600160a01b031663be8da14b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ff91906148a8565b9050600061130d828661142f565b905061133683826bffffffffffffffffffffffff16866bffffffffffffffffffffffff1661368a565b6113535760405163f06fc6e760e01b815260040160405180910390fd5b611426826040518060400160405280601d81526020017f736574546f6b656e4c696d697428616464726573732c75696e7439362900000081525087876040516020016113c29291906001600160a01b039290921682526bffffffffffffffffffffffff16602082015260400190565b60408051601f19818403018152918152600088815260016020522054600160a81b900464ffffffffff166040516001600160a01b0388811660248301528b1660448201526bffffffffffffffffffffffff871690309063484b8e9690606401610c8c565b50505050505050565b60405163bd42a06f60e01b81526001600160a01b038281166004830152600091829185169063bd42a06f9060240160c060405180830381865afa15801561147a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149e9190614929565b5098975050505050505050565b6001600160a01b03811660009081526002602052604090208054606091906114d290614747565b80601f01602080910402602001604051908101604052809291908181526020018280546114fe90614747565b801561154b5780601f106115205761010080835404028352916020019161154b565b820191906000526020600020905b81548152906001019060200180831161152e57829003601f168201915b50505050509050919050565b6001600160a01b0382166000908152600260209081526040808320905161157e92016149cd565b6040516020818303038152906040528051906020012090506000836001600160a01b031663e941fa786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fa9190614862565b61ffff16905061160b82828561368a565b6116285760405163f06fc6e760e01b815260040160405180910390fd5b6116c3846040518060400160405280601781526020017f73657457697468647261774665652875696e74323536290000000000000000008152508560405160200161167591815260200190565b60408051601f19818403018152918152600087815260016020522054600160a81b900464ffffffffff166040516001600160a01b038a166024820152869030906354ecd60890604401610c8c565b5050505050565b6000816001600160a01b031663e941fa786040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190614862565b61ffff1692915050565b6000816001600160a01b031663183ace906040518163ffffffff1660e01b8152600401602060405180830381865afa158015611778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a9190614a1f565b6117a4613c31565b6000818152600160209081526040808320805460ff191690555191825282917fe7d3ad39af384f74aa98471d169bf505294494fe423d16402df3ce2a37584314910160405180910390a250565b6000826001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611831573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185591906148a8565b90506000836001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611897573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118bb91906148a8565b905060006118c882610950565b9050611908856040518060400160405280600881526020016713505617d111509560c21b815250836001600160801b0316876001600160801b0316613ae0565b6119255760405163f06fc6e760e01b815260040160405180910390fd5b610ecd836040518060400160405280601881526020017f7365744d6178446562744c696d69742875696e743132382900000000000000008152508660405160200161197f91906001600160801b0391909116815260200190565b60408051601f19818403018152828201909152600882526713505617d111509560c21b6020830152906119b3908a90613b39565b6040516001600160a01b03881660248201526001600160801b03871690309063280e56a490604401610c8c565b6001600160a01b03821660009081526002602090815260408083209051611a079201614a38565b6040516020818303038152906040528051906020012090506000611a2a84611738565b9050611a3782828561368a565b611a545760405163f06fc6e760e01b815260040160405180910390fd5b6116c3846040518060400160405280601a81526020017f736574546f74616c446562744c696d69742875696e743235362900000000000081525085604051602001611aa191815260200190565b60408051601f19818403018152918152600087815260016020522054600160a81b900464ffffffffff166040516001600160a01b038a166024820152869030906358d1ca6e90604401610c8c565b6000826001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5391906148a8565b90506000836001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb991906148a8565b90506000846001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1f91906148a8565b90506000611c2c826108e6565b9050611c7d866040518060400160405280600f81526020017f45585049524154494f4e5f4441544500000000000000000000000000000000008152508364ffffffffff168864ffffffffff16613ae0565b611c9a5760405163f06fc6e760e01b815260040160405180910390fd5b6040517f7a99c0170000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015260009190851690637a99c01790602401602060405180830381865afa158015611cfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d219190614a1f565b90508015611d425760405163f06fc6e760e01b815260040160405180910390fd5b611e0e856040518060400160405280601981526020017f73657445787069726174696f6e446174652875696e743430290000000000000081525088604051602001611d9a919064ffffffffff91909116815260200190565b60408051601f19818403018152828201909152600f82527f45585049524154494f4e5f444154450000000000000000000000000000000000602083015290611de3908c90613b39565b6040516001600160a01b038916602482015264ffffffffff8816903090632522f8da90604401610c8c565b5050505050505050565b6001600160a01b038084166000908152600260209081526040808320938616835280832090519293611e4c93909201614a8a565b604051602081830303815290604052805190602001209050611e708160008061368a565b611e8d5760405163f06fc6e760e01b815260040160405180910390fd5b6116c38460405180606001604052806027815260200161509f60279139604080516001600160a01b03881660208201528615159181019190915260600160408051601f19818403018152918152600086815260016020522054600160a81b900464ffffffffff16610fbd565b611f01613c70565b600081815260046020526040808220805460ff191690555182917fbb8e18922d3abb7d8aea19f1b55d85b0ee985798c196aad6d05c58dfdb7c98af91a250565b600080826001600160a01b031663166bf9d96040518163ffffffff1660e01b81526004016040805180830381865afa158015611f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa591906146b9565b509392505050565b6000826001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201191906148a8565b9050600061201f8285612c65565b9050612062846040518060400160405280601981526020017f4352454449545f4d414e414745525f444542545f4c494d4954000000000000008152508386613ae0565b61207f5760405163f06fc6e760e01b815260040160405180910390fd5b6116c3826040518060600160405280602a815260200161511e602a9139604080516001600160a01b038916602082015290810187905260600160408051601f19818403018152828201909152601982527f4352454449545f4d414e414745525f444542545f4c494d495400000000000000602083015290612101908990613b39565b6040516001600160a01b0388811660248301528a1660448201528690309063c9eea26c90606401610c8c565b60405163bd42a06f60e01b81526001600160a01b038281166004830152600091829185169063bd42a06f9060240160c060405180830381865afa158015612178573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219c9190614929565b509198975050505050505050565b6121b2613cb4565b610fe8613cf3565b6121c2613c31565b6001600160a01b03831660009081526002602052604090206121e5828483614b39565b5081816040516121f6929190614bf9565b604051908190038120906001600160a01b038516907f92862d5b730cd2540433b48d4973472ba23dcd95d056d22098ebc8ac3d6c741d90600090a3505050565b6001600160a01b0382166000908152600260209081526040808320905161225d9201614c09565b6040516020818303038152906040528051906020012090506000836001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d991906148a8565b90506122e78260008061368a565b6123045760405163f06fc6e760e01b815260040160405180910390fd5b6116c3816040518060400160405280601681526020017f666f7262696441646170746572286164647265737329000000000000000000008152508560405160200161235e91906001600160a01b0391909116815260200190565b60408051601f19818403018152918152600087815260016020522054600160a81b900464ffffffffff16610fbd565b6000816001600160a01b031663a384d6ff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611778573d6000803e3d6000fd5b6123d5613c31565b6003546001600160a01b0382811691161461244a57600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f186cb628766b6429a759e2bca5d79296f60bfb05a03df1f892e5fba8b03be33590600090a25b50565b60006124588361238d565b905061249b836040518060400160405280601581526020017f4c505f50524943455f464545445f4c494d4954455200000000000000000000008152508385613ae0565b6124b85760405163f06fc6e760e01b815260040160405180910390fd5b612572836040518060400160405280601381526020017f7365744c696d697465722875696e7432353629000000000000000000000000008152508460405160200161250591815260200190565b60408051601f19818403018152828201909152601582527f4c505f50524943455f464545445f4c494d49544552000000000000000000000060208301529061254e908890613b39565b6040516001600160a01b038916602482015286903090638bf1695e90604401610c8c565b50505050565b612580613c31565b6000546001600160a01b0382811662010000909204161461244a57600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff16620100006001600160a01b03841690810291909117825560405190917fe253457d9ad994ca9682fc3bbc38c890dca73a2d5ecee3809e548bac8b00d7c691a250565b6040517f3201de4c0000000000000000000000000000000000000000000000000000000081526001600160a01b038281166004830152600091829182918291829190881690633201de4c90602401608060405180830381865afa15801561266e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126929190614c5b565b6040805161ffff958616602080830191909152949095168582015264ffffffffff92909216606085015262ffffff166080808501919091528151808503909101815260a090930190528151910120979650505050505050565b6040516305b23b1160e11b81526001600160a01b0382811660048301526000918291851690630b64762290602401608060405180830381865afa158015612736573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275a91906146e8565b50919695505050505050565b600081815260046020908152604080832081516101008082018452825460ff811615158352046001600160a01b0390811694820194909452600182015493841692810192909252600160a01b90920464ffffffffff1660608201526002820180549192916080840191906127d990614747565b80601f016020809104026020016040519081016040528092919081815260200182805461280590614747565b80156128525780601f1061282757610100808354040283529160200191612852565b820191906000526020600020905b81548152906001019060200180831161283557829003601f168201915b5050505050815260200160038201805461286b90614747565b80601f016020809104026020016040519081016040528092919081815260200182805461289790614747565b80156128e45780601f106128b9576101008083540402835291602001916128e4565b820191906000526020600020905b8154815290600101906020018083116128c757829003601f168201915b505050505081526020016004820154815260200160058201805461290790614747565b80601f016020809104026020016040519081016040528092919081815260200182805461293390614747565b80156129805780601f1061295557610100808354040283529160200191612980565b820191906000526020600020905b81548152906001019060200180831161296357829003601f168201915b505050505081525050905080600001516129c6576040517f47a157cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80602001516001600160a01b0316336001600160a01b031614612a15576040517f737d8ae200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408101516060820151608083015160a084015164ffffffffff8316421080612a505750612a4d6212750064ffffffffff8516614895565b42115b15612a87576040517f564de7fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60e08501515115612b46576000306001600160a01b03168660e00151604051612ab09190614caf565b600060405180830381855afa9150503d8060008114612aeb576040519150601f19603f3d011682016040523d82523d6000602084013e612af0565b606091505b509150508560c0015181806020019051810190612b0d9190614a1f565b14612b44576040517f0a5f425900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b6000868152600460205260408120805460ff19169055825160609103612b6d575080612b99565b828051906020012082604051602001612b87929190614ccb565b60405160208183030381529060405290505b6000856001600160a01b031682604051612bb39190614caf565b6000604051808303816000865af19150503d8060008114612bf0576040519150601f19603f3d011682016040523d82523d6000602084013e612bf5565b606091505b5050905080612c30576040517fdc3f6c3300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405188907fef9d8cdf871686f540056b412c18c767afeb6ec3fe4040634ad43b192643103a90600090a25050505050505050565b6040517fb0df2c660000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000919084169063b0df2c6690602401602060405180830381865afa158015612cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cec9190614a1f565b9392505050565b6000816001600160a01b031663478ade366040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d33573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a9190614d13565b6001600160a01b038084166000908152600260209081526040808320938616835280832090519293612d8b93909201614d30565b6040516020818303038152906040528051906020012090506000846001600160a01b031663be8da14b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612de3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e0791906148a8565b90506000816001600160a01b031663a6f19c846040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6d91906148a8565b90506000612e7b82876109bc565b9050612e90848261ffff168761ffff1661368a565b612ead5760405163f06fc6e760e01b815260040160405180910390fd5b611e0e826040518060600160405280602281526020016150c660229139604080516001600160a01b038b16602082015261ffff8a169181019190915260600160408051601f19818403018152918152600089815260016020522054600160a81b900464ffffffffff166040516001600160a01b0388811660248301528c16604482015261ffff8716903090632a61e76c90606401610c8c565b60046020526000908152604090208054600182015460028301805460ff8416946001600160a01b0361010090950485169484169364ffffffffff600160a01b90910416929091612f9590614747565b80601f0160208091040260200160405190810160405280929190818152602001828054612fc190614747565b801561300e5780601f10612fe35761010080835404028352916020019161300e565b820191906000526020600020905b815481529060010190602001808311612ff157829003601f168201915b50505050509080600301805461302390614747565b80601f016020809104026020016040519081016040528092919081815260200182805461304f90614747565b801561309c5780601f106130715761010080835404028352916020019161309c565b820191906000526020600020905b81548152906001019060200180831161307f57829003601f168201915b5050505050908060040154908060050180546130b790614747565b80601f01602080910402602001604051908101604052809291908181526020018280546130e390614747565b80156131305780601f1061310557610100808354040283529160200191613130565b820191906000526020600020905b81548152906001019060200180831161311357829003601f168201915b5050505050905088565b6001600160a01b03808416600090815260026020908152604080832093861683528083209051929361316e93909201614d94565b6040516020818303038152906040528051906020012090506000846001600160a01b031663be8da14b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ea91906148a8565b905060006131f8828661212d565b905061320d838261ffff168661ffff1661368a565b61322a5760405163f06fc6e760e01b815260040160405180910390fd5b6114268260405180606001604052806028815260200161507760289139604080516001600160a01b038a16602082015261ffff89169181019190915260600160408051601f19818403018152918152600088815260016020522054600160a81b900464ffffffffff166040516001600160a01b0388811660248301528b16604482015261ffff8716903090637fd8067c90606401610c8c565b6001600160a01b0380841660009081526002602090815260408083209386168352808320905192936132f793909201614df8565b6040516020818303038152906040528051906020012090506000846001600160a01b031663be8da14b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561334f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061337391906148a8565b90506000816001600160a01b031663a6f19c846040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133d991906148a8565b905060006133e782876126eb565b90506133fc848261ffff168761ffff1661368a565b6134195760405163f06fc6e760e01b815260040160405180910390fd5b611e0e8260405180606001604052806022815260200161514860229139604080516001600160a01b038b16602082015261ffff8a169181019190915260600160408051601f19818403018152918152600089815260016020522054600160a81b900464ffffffffff166040516001600160a01b0388811660248301528c16604482015261ffff871690309063c091301c90606401610c8c565b6000826001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061351691906148a8565b90506000836001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015613558573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357c91906148a8565b9050600061358982612cf3565b90506135d2856040518060400160405280601d81526020017f4d41585f444542545f5045525f424c4f434b5f4d554c5449504c4945520000008152508360ff168760ff16613ae0565b6135ef5760405163f06fc6e760e01b815260040160405180910390fd5b610ecd8360405180606001604052806023815260200161516a602391396040805160ff891660208201520160408051601f19818403018152828201909152601d82527f4d41585f444542545f5045525f424c4f434b5f4d554c5449504c494552000000602083015290613663908a90613b39565b6040516001600160a01b038816602482015260ff871690309063ea26c43390604401610c8c565b6000838152600160205260408120805460ff166136ab576000915050612cec565b805461010090046001600160a01b031633146136cb576000915050612cec565b8054600160d01b900460ff811690600116156136f757816001015484146136f757600092505050612cec565b600281161561371757816002015484101561371757600092505050612cec565b600481161561373757816003015484111561373757600092505050612cec565b600060788216156138e45760058301546137649064ffffffffff8082169165010000000000900416614e5c565b64ffffffffff164211156137a657506004820185905560058201805469ffffffffff00000000001916650100000000004264ffffffffff1602179055846137ad565b5060048201545b6000806137ba8784613d30565b909250905060088416156137e25784600601548210156137e257600095505050505050612cec565b601084161561380557846007015482111561380557600095505050505050612cec565b60608416156138e15760008361381d61271085614e81565b6138279190614e98565b905060208516158015906138785750816138575760058601546a0100000000000000000000900461ffff16613871565b60058601546c01000000000000000000000000900461ffff165b61ffff1681105b1561388c5760009650505050505050612cec565b60408516158015906138cb5750816138b3576005860154600160701b900461ffff166138c4565b6005860154600160801b900461ffff165b61ffff1681115b156138df5760009650505050505050612cec565b505b50505b5060019695505050505050565b6000806138fe8542614895565b90506000338989898560405160200161391b959493929190614eba565b604051602081830303815290604052805190602001209050604051806101000160405280600115158152602001336001600160a01b031681526020018a6001600160a01b031681526020018364ffffffffff168152602001898152602001888152602001868152602001858152506004600083815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160010160146101000a81548164ffffffffff021916908364ffffffffff1602179055506080820151816002019081613a549190614f0b565b5060a08201516003820190613a699082614f0b565b5060c0820151600482015560e08201516005820190613a889082614f0b565b50905050336001600160a01b0316817fcbc0420b9ccad04c18c723bfad07db88131bc78c76ca44827afdd7784d3ddfe28b8b8b87604051613acc9493929190614fcb565b60405180910390a398975050505050505050565b6001600160a01b038416600090815260026020908152604080832090518392613b0c9291889101615018565b604051602081830303815290604052805190602001209050613b2f81858561368a565b9695505050505050565b6001600160a01b038216600090815260026020908152604080832090518392613b659291869101615018565b60408051808303601f19018152918152815160209283012060009081526001909252902054600160a81b900464ffffffffff16949350505050565b613ba933613d63565b610fe8576040517f16e29ab700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613be7613e0c565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b613c3a33613e63565b610fe8576040517f61081c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003546001600160a01b03163314610fe8576040517f349beb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613cbd33613ecf565b610fe8576040517fd794b1e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613cfb613f3b565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613c143390565b600080828411613d4b57613d448484615046565b6000613d58565b613d558385615046565b60015b915091509250929050565b6040517fd4eb5db00000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000ad131da4bddb40ebb5ceeaea87067553d43138959091169063d4eb5db0906024015b602060405180830381865afa158015613de8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094a9190615059565b60005460ff16610fe85760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064015b60405180910390fd5b6040517f5f259aba0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000ad131da4bddb40ebb5ceeaea87067553d431389590911690635f259aba90602401613dcb565b6040517f3a41ec640000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f000000000000000000000000ad131da4bddb40ebb5ceeaea87067553d431389590911690633a41ec6490602401613dcb565b60005460ff1615610fe85760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401613e5a565b6001600160a01b038116811461244a57600080fd5b8035613fae81613f8e565b919050565b600060208284031215613fc557600080fd5b8135612cec81613f8e565b60008060408385031215613fe357600080fd5b8235613fee81613f8e565b91506020830135613ffe81613f8e565b809150509250929050565b61ffff8116811461244a57600080fd5b8035613fae81614009565b64ffffffffff8116811461244a57600080fd5b8035613fae81614024565b62ffffff8116811461244a57600080fd5b600080600080600060a0868803121561406b57600080fd5b853561407681613f8e565b9450602086013561408681613f8e565b9350604086013561409681614009565b925060608601356140a681614024565b915060808601356140b681614042565b809150509295509295909350565b6001600160801b038116811461244a57600080fd5b600080604083850312156140ec57600080fd5b82356140f781613f8e565b91506020830135613ffe816140c4565b634e487b7160e01b600052604160045260246000fd5b604051610200810167ffffffffffffffff8111828210171561414157614141614107565b60405290565b801515811461244a57600080fd5b8035613fae81614147565b60ff8116811461244a57600080fd5b8035613fae81614160565b60008082840361022081121561418f57600080fd5b8335925061020080601f19830112156141a757600080fd5b6141af61411d565b91506141bd60208601614155565b82526141cb60408601613fa3565b60208301526141dc60608601614037565b60408301526141ed6080860161416f565b606083015260a0850135608083015260c085013560a083015260e085013560c08301526101008086013560e084015261012061422a818801614037565b82850152610140915061423e828801614037565b90840152610160614250878201614019565b828501526101809150614264828801614019565b908401526101a0614276878201614019565b828501526101c0915061428a828801614019565b908401526101e08681013591840191909152940135938101939093525092909150565b6bffffffffffffffffffffffff8116811461244a57600080fd5b6000806000606084860312156142dc57600080fd5b83356142e781613f8e565b925060208401356142f781613f8e565b91506040840135614307816142ad565b809150509250925092565b60005b8381101561432d578181015183820152602001614315565b50506000910152565b6000815180845261434e816020860160208601614312565b601f01601f19169290920160200192915050565b602081526000612cec6020830184614336565b6000806040838503121561438857600080fd5b823561439381613f8e565b946020939093013593505050565b6000602082840312156143b357600080fd5b5035919050565b600080604083850312156143cd57600080fd5b82356143d881613f8e565b91506020830135613ffe81614024565b6000806000606084860312156143fd57600080fd5b833561440881613f8e565b9250602084013561441881613f8e565b9150604084013561430781614147565b60008060006040848603121561443d57600080fd5b833561444881613f8e565b9250602084013567ffffffffffffffff8082111561446557600080fd5b818601915086601f83011261447957600080fd5b81358181111561448857600080fd5b87602082850101111561449a57600080fd5b6020830194508093505050509250925092565b815115158152610200810160208301516144d260208401826001600160a01b03169052565b5060408301516144eb604084018264ffffffffff169052565b506060830151614500606084018260ff169052565b506080830151608083015260a083015160a083015260c083015160c083015260e083015160e0830152610100808401516145428285018264ffffffffff169052565b50506101208381015164ffffffffff16908301526101408084015161ffff9081169184019190915261016080850151821690840152610180808501518216908401526101a080850151909116908301526101c080840151908301526101e092830151929091019190915290565b6000806000606084860312156145c457600080fd5b83356145cf81613f8e565b925060208401356145df81613f8e565b9150604084013561430781614009565b60006101008a151583526001600160a01b03808b166020850152808a1660408501525064ffffffffff8816606084015280608084015261463181840188614336565b905082810360a08401526146458187614336565b90508460c084015282810360e084015261465f8185614336565b9b9a5050505050505050505050565b6000806040838503121561468157600080fd5b823561468c81613f8e565b91506020830135613ffe81614160565b6000602082840312156146ae57600080fd5b8151612cec81614024565b600080604083850312156146cc57600080fd5b82516146d7816140c4565b6020840151909250613ffe816140c4565b600080600080608085870312156146fe57600080fd5b845161470981614009565b602086015190945061471a81614009565b604086015190935061472b816142ad565b606086015190925061473c816142ad565b939692955090935050565b600181811c9082168061475b57607f821691505b60208210810361477b57634e487b7160e01b600052602260045260246000fd5b50919050565b6000815461478e81614747565b8085526020600183811680156147ab57600181146147c5576147f3565b60ff1985168884015283151560051b8801830195506147f3565b866000528260002060005b858110156147eb5781548a82018601529083019084016147d0565b890184019650505b505050505092915050565b6060815260006148116060830185614781565b82810360208401526148238185614781565b838103604094850152600881527f544f4b454e5f4c54000000000000000000000000000000000000000000000000602082015292909201949350505050565b60006020828403121561487457600080fd5b8151612cec81614009565b634e487b7160e01b600052601160045260246000fd5b8082018082111561094a5761094a61487f565b6000602082840312156148ba57600080fd5b8151612cec81613f8e565b6060815260006148d86060830185614781565b82810360208401526148ea8185614781565b838103604094850152600b81527f544f4b454e5f4c494d4954000000000000000000000000000000000000000000602082015292909201949350505050565b60008060008060008060c0878903121561494257600080fd5b865161494d81614009565b602088015190965077ffffffffffffffffffffffffffffffffffffffffffffffff8116811461497b57600080fd5b604088015190955061498c81614009565b606088015190945061499d816142ad565b60808801519093506149ae816142ad565b60a08801519092506149bf81614147565b809150509295509295509295565b6040815260006149e06040830184614781565b8281036020840152600c81527f57495448445241575f464545000000000000000000000000000000000000000060208201526040810191505092915050565b600060208284031215614a3157600080fd5b5051919050565b604081526000614a4b6040830184614781565b8281036020840152601081527f544f54414c5f444542545f4c494d49540000000000000000000000000000000060208201526040810191505092915050565b606081526000614a9d6060830185614781565b8281036020840152614aaf8185614781565b838103604094850152601981527f524553455256455f50524943455f464545445f53544154555300000000000000602082015292909201949350505050565b601f821115614b3457600081815260208120601f850160051c81016020861015614b155750805b601f850160051c820191505b81811015610ecd57828155600101614b21565b505050565b67ffffffffffffffff831115614b5157614b51614107565b614b6583614b5f8354614747565b83614aee565b6000601f841160018114614b995760008515614b815750838201355b600019600387901b1c1916600186901b1783556116c3565b600083815260209020601f19861690835b82811015614bca5786850135825560209485019460019092019101614baa565b5086821015614be75760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8183823760009101908152919050565b604081526000614c1c6040830184614781565b8281036020840152600e81527f464f524249445f4144415054455200000000000000000000000000000000000060208201526040810191505092915050565b60008060008060808587031215614c7157600080fd5b8451614c7c81614009565b6020860151909450614c8d81614009565b6040860151909350614c9e81614024565b606086015190925061473c81614042565b60008251614cc1818460208701614312565b9190910192915050565b7fffffffff000000000000000000000000000000000000000000000000000000008316815260008251614d05816004850160208701614312565b919091016004019392505050565b600060208284031215614d2557600080fd5b8151612cec81614160565b606081526000614d436060830185614781565b8281036020840152614d558185614781565b838103604094850152601481527f544f4b454e5f51554f54415f4d41585f52415445000000000000000000000000602082015292909201949350505050565b606081526000614da76060830185614781565b8281036020840152614db98185614781565b838103604094850152601881527f544f4b454e5f51554f54415f494e4352454153455f4645450000000000000000602082015292909201949350505050565b606081526000614e0b6060830185614781565b8281036020840152614e1d8185614781565b838103604094850152601481527f544f4b454e5f51554f54415f4d494e5f52415445000000000000000000000000602082015292909201949350505050565b64ffffffffff818116838216019080821115614e7a57614e7a61487f565b5092915050565b808202811582820484141761094a5761094a61487f565b600082614eb557634e487b7160e01b600052601260045260246000fd5b500490565b60006001600160a01b03808816835280871660208401525060a06040830152614ee660a0830186614336565b8281036060840152614ef88186614336565b9150508260808301529695505050505050565b815167ffffffffffffffff811115614f2557614f25614107565b614f3981614f338454614747565b84614aee565b602080601f831160018114614f6e5760008415614f565750858301515b600019600386901b1c1916600185901b178555610ecd565b600085815260208120601f198616915b82811015614f9d57888601518255948401946001909101908401614f7e565b5085821015614fbb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385168152608060208201526000614fed6080830186614336565b8281036040840152614fff8186614336565b91505064ffffffffff8316606083015295945050505050565b60408152600061502b6040830185614781565b828103602084015261503d8185614336565b95945050505050565b8181038181111561094a5761094a61487f565b60006020828403121561506b57600080fd5b8151612cec8161414756fe736574546f6b656e51756f7461496e63726561736546656528616464726573732c75696e743136297365745265736572766550726963654665656453746174757328616464726573732c626f6f6c296368616e676551756f74614d61785261746528616464726573732c75696e7431362972616d704c69717569646174696f6e5468726573686f6c6428616464726573732c75696e7431362c75696e7434302c75696e743234297365744372656469744d616e61676572446562744c696d697428616464726573732c75696e74323536296368616e676551756f74614d696e5261746528616464726573732c75696e743136297365744d617844656274506572426c6f636b4d756c7469706c6965722875696e743829a26469706673582212208401e7290eef9f3ddd3f43d43ded6aa00f0dea65b02e5292c0cb90cbd613b3a964736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004b27b296273b72d7c7bfee1ace93dc081467c41b000000000000000000000000393ec629b90389f957c5a2e4fc2f8f488e735bfc
-----Decoded View---------------
Arg [0] : _addressProvider (address): 0x4b27b296273B72d7c7bfee1ACE93DC081467C41B
Arg [1] : _vetoAdmin (address): 0x393eC629b90389F957c5a2E4FC2F8F488e735BFC
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004b27b296273b72d7c7bfee1ace93dc081467c41b
Arg [1] : 000000000000000000000000393ec629b90389f957c5a2e4fc2f8f488e735bfc
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.