Overview
MON Balance
MON Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 35732753 | 75 days ago | Contract Creation | 0 MON |
Loading...
Loading
Contract Name:
CreditFactory
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 1000 runs
Other Settings:
shanghai 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, 2025.
pragma solidity ^0.8.23;
import {IAccountFactory} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IAccountFactory.sol";
import {IAdapter} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IAdapter.sol";
import {ICreditConfiguratorV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditConfiguratorV3.sol";
import {ICreditFacadeV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditFacadeV3.sol";
import {ICreditManagerV3} from "@gearbox-protocol/core-v3/contracts/interfaces/ICreditManagerV3.sol";
import {IPoolV3} from "@gearbox-protocol/core-v3/contracts/interfaces/IPoolV3.sol";
import {ICreditFactory} from "../interfaces/factories/ICreditFactory.sol";
import {
CreditFacadeParams,
CreditManagerParams,
ICreditConfigureActions
} from "../interfaces/factories/ICreditConfigureActions.sol";
import {ICreditEmergencyConfigureActions} from "../interfaces/factories/ICreditEmergencyConfigureActions.sol";
import {IFactory} from "../interfaces/factories/IFactory.sol";
import {IContractsRegister} from "../interfaces/IContractsRegister.sol";
import {IMarketConfigurator} from "../interfaces/IMarketConfigurator.sol";
import {Call, DeployParams, DeployResult} from "../interfaces/Types.sol";
import {CallBuilder} from "../libraries/CallBuilder.sol";
import {
DOMAIN_ACCOUNT_FACTORY,
DOMAIN_ADAPTER,
DOMAIN_CREDIT_MANAGER,
DOMAIN_DEGEN_NFT,
AP_BOT_LIST,
AP_CREDIT_CONFIGURATOR,
AP_CREDIT_FACADE,
AP_CREDIT_FACTORY,
AP_WETH_TOKEN,
NO_VERSION_CONTROL
} from "../libraries/ContractLiterals.sol";
import {AbstractFactory} from "./AbstractFactory.sol";
contract CreditFactory is AbstractFactory, ICreditFactory {
uint256 public constant override version = 3_10;
bytes32 public constant override contractType = AP_CREDIT_FACTORY;
address public immutable botList;
error DegenNFTIsNotRegisteredException(address degenNFT);
error TargetContractIsNotAllowedException(address targetCotnract);
constructor(address addressProvider_) AbstractFactory(addressProvider_) {
botList = _getAddressOrRevert(AP_BOT_LIST, NO_VERSION_CONTROL);
}
// ---------- //
// DEPLOYMENT //
// ---------- //
function deployCreditSuite(address pool, bytes calldata encodedParams)
external
override
onlyMarketConfigurators
returns (DeployResult memory)
{
(CreditManagerParams memory params, CreditFacadeParams memory facadeParams) =
abi.decode(encodedParams, (CreditManagerParams, CreditFacadeParams));
address accountFactory = _deployAccountFactory(msg.sender, params.accountFactoryParams);
address creditManager = _deployCreditManager(msg.sender, pool, accountFactory, params);
address creditConfigurator = _deployCreditConfigurator(msg.sender, creditManager);
address creditFacade = _deployCreditFacade(msg.sender, creditManager, facadeParams);
IAccountFactory(accountFactory).addCreditManager(creditManager);
ICreditManagerV3(creditManager).setCreditConfigurator(creditConfigurator);
return DeployResult({
newContract: creditManager,
onInstallOps: CallBuilder.build(
_authorizeFactory(msg.sender, creditManager, creditConfigurator),
_authorizeFactory(msg.sender, creditManager, creditFacade),
_setCreditFacade(creditConfigurator, creditFacade, false),
_setDebtLimits(creditConfigurator, params.minDebt, params.maxDebt)
)
});
}
function computeCreditManagerAddress(
address marketConfigurator,
address pool,
address underlying,
address priceOracle,
bytes calldata encodedParams
) external view override returns (address) {
(CreditManagerParams memory params,) = abi.decode(encodedParams, (CreditManagerParams, CreditFacadeParams));
return _computeCreditManagerAddress(marketConfigurator, pool, underlying, priceOracle, params);
}
// ------------ //
// CREDIT HOOKS //
// ------------ //
function onUpdatePriceOracle(address creditManager, address newPriceOracle, address)
external
view
override
returns (Call[] memory)
{
return CallBuilder.build(_setPriceOracle(_creditConfigurator(creditManager), newPriceOracle));
}
function onUpdateLossPolicy(address creditManager, address newLossPolicy, address)
external
view
override
returns (Call[] memory)
{
return CallBuilder.build(_setLossPolicy(_creditConfigurator(creditManager), newLossPolicy));
}
// ------------- //
// CONFIGURATION //
// ------------- //
function configure(address creditManager, bytes calldata callData)
external
override(AbstractFactory, IFactory)
onlyMarketConfigurators
returns (Call[] memory)
{
bytes4 selector = bytes4(callData);
if (selector == ICreditConfigureActions.upgradeCreditConfigurator.selector) {
address creditConfigurator = _creditConfigurator(creditManager);
address newCreditConfigurator = _deployCreditConfigurator(msg.sender, creditManager);
return CallBuilder.build(
_upgradeCreditConfigurator(creditConfigurator, newCreditConfigurator),
_unauthorizeFactory(msg.sender, creditManager, creditConfigurator),
_authorizeFactory(msg.sender, creditManager, newCreditConfigurator),
_makeAllTokensQuoted(newCreditConfigurator)
);
} else if (selector == ICreditConfigureActions.upgradeCreditFacade.selector) {
CreditFacadeParams memory params = abi.decode(callData[4:], (CreditFacadeParams));
address creditFacade = _creditFacade(creditManager);
address newCreditFacade = _deployCreditFacade(msg.sender, creditManager, params);
return CallBuilder.build(
_setCreditFacade(_creditConfigurator(creditManager), newCreditFacade, true),
_unauthorizeFactory(msg.sender, creditManager, creditFacade),
_authorizeFactory(msg.sender, creditManager, newCreditFacade)
);
} else if (selector == ICreditConfigureActions.allowAdapter.selector) {
DeployParams memory params = abi.decode(callData[4:], (DeployParams));
address adapter = _deployAdapter(msg.sender, creditManager, params);
address oldAdapter = ICreditManagerV3(creditManager).contractToAdapter(IAdapter(adapter).targetContract());
Call memory unauthorizeCall = _unauthorizeFactory(msg.sender, creditManager, oldAdapter);
Call memory authorizeCall = _authorizeFactory(msg.sender, creditManager, adapter);
Call memory allowCall = _allowAdapter(_creditConfigurator(creditManager), adapter);
return oldAdapter != address(0)
? CallBuilder.build(unauthorizeCall, authorizeCall, allowCall)
: CallBuilder.build(authorizeCall, allowCall);
} else if (selector == ICreditConfigureActions.forbidAdapter.selector) {
address adapter = abi.decode(callData[4:], (address));
return CallBuilder.build(
_unauthorizeFactory(msg.sender, creditManager, adapter),
_forbidAdapter(_creditConfigurator(creditManager), adapter)
);
} else if (selector == ICreditConfigureActions.configureAdapterFor.selector) {
(address targetContract, bytes memory data) = abi.decode(callData[4:], (address, bytes));
address adapter = ICreditManagerV3(creditManager).contractToAdapter(targetContract);
if (adapter == address(0)) revert TargetContractIsNotAllowedException(targetContract);
return CallBuilder.build(Call(adapter, data));
} else if (
selector == ICreditConfigureActions.setFees.selector
|| selector == ICreditConfigureActions.setMaxDebtPerBlockMultiplier.selector
|| selector == ICreditConfigureActions.addCollateralToken.selector
|| selector == ICreditConfigureActions.rampLiquidationThreshold.selector
|| selector == ICreditConfigureActions.forbidToken.selector
|| selector == ICreditConfigureActions.allowToken.selector
|| selector == ICreditConfigureActions.setExpirationDate.selector
) {
return CallBuilder.build(Call(_creditConfigurator(creditManager), callData));
} else if (
selector == ICreditConfigureActions.pause.selector || selector == ICreditConfigureActions.unpause.selector
) {
return CallBuilder.build(Call(_creditFacade(creditManager), callData));
} else {
revert ForbiddenConfigurationCallException(selector);
}
}
function emergencyConfigure(address creditManager, bytes calldata callData)
external
view
override(AbstractFactory, IFactory)
returns (Call[] memory)
{
bytes4 selector = bytes4(callData);
if (selector == ICreditEmergencyConfigureActions.forbidAdapter.selector) {
address adapter = abi.decode(callData[4:], (address));
return CallBuilder.build(
_unauthorizeFactory(msg.sender, creditManager, adapter),
_forbidAdapter(_creditConfigurator(creditManager), adapter)
);
} else if (
selector == ICreditEmergencyConfigureActions.forbidBorrowing.selector
|| selector == ICreditEmergencyConfigureActions.forbidToken.selector
) {
return CallBuilder.build(Call(_creditConfigurator(creditManager), callData));
} else if (selector == ICreditEmergencyConfigureActions.pause.selector) {
return CallBuilder.build(Call(_creditFacade(creditManager), callData));
} else {
revert ForbiddenEmergencyConfigurationCallException(selector);
}
}
// --------- //
// INTERNALS //
// --------- //
function _deployAccountFactory(address marketConfigurator, DeployParams memory params) internal returns (address) {
address decodedAddressProvider = abi.decode(params.constructorParams, (address));
if (decodedAddressProvider != addressProvider) revert InvalidConstructorParamsException();
return _deployLatestPatch({
contractType: _getContractType(DOMAIN_ACCOUNT_FACTORY, params.postfix),
minorVersion: version,
constructorParams: params.constructorParams,
salt: keccak256(abi.encode(params.salt, marketConfigurator))
});
}
function _computeAccountFactoryAddress(address marketConfigurator, DeployParams memory params)
internal
view
returns (address)
{
return _computeAddressLatestPatch({
contractType: _getContractType(DOMAIN_ACCOUNT_FACTORY, params.postfix),
minorVersion: version,
constructorParams: params.constructorParams,
salt: keccak256(abi.encode(params.salt, marketConfigurator)),
deployer: address(this)
});
}
function _deployCreditManager(
address marketConfigurator,
address pool,
address accountFactory,
CreditManagerParams memory params
) internal returns (address) {
bytes32 postfix = _getTokenSpecificPostfix(IPoolV3(pool).asset());
address contractsRegister = IMarketConfigurator(marketConfigurator).contractsRegister();
address priceOracle = IContractsRegister(contractsRegister).getPriceOracle(pool);
bytes memory constructorParams = _buildCreditManagerConstructorParams(pool, accountFactory, priceOracle, params);
return _deployLatestPatch({
contractType: _getContractType(DOMAIN_CREDIT_MANAGER, postfix),
minorVersion: version,
constructorParams: constructorParams,
salt: bytes32(bytes20(marketConfigurator))
});
}
function _computeCreditManagerAddress(
address marketConfigurator,
address pool,
address underlying,
address priceOracle,
CreditManagerParams memory params
) internal view returns (address) {
address accountFactory = _computeAccountFactoryAddress(marketConfigurator, params.accountFactoryParams);
bytes32 postfix = _getTokenSpecificPostfix(underlying);
bytes memory constructorParams = _buildCreditManagerConstructorParams(pool, accountFactory, priceOracle, params);
return _computeAddressLatestPatch({
contractType: _getContractType(DOMAIN_CREDIT_MANAGER, postfix),
minorVersion: version,
constructorParams: constructorParams,
salt: bytes32(bytes20(marketConfigurator)),
deployer: address(this)
});
}
function _buildCreditManagerConstructorParams(
address pool,
address accountFactory,
address priceOracle,
CreditManagerParams memory params
) internal pure returns (bytes memory) {
return abi.encode(
pool,
accountFactory,
priceOracle,
params.maxEnabledTokens,
params.feeInterest,
params.feeLiquidation,
params.liquidationPremium,
params.feeLiquidationExpired,
params.liquidationPremiumExpired,
params.name
);
}
function _deployCreditConfigurator(address marketConfigurator, address creditManager) internal returns (address) {
bytes memory constructorParams = abi.encode(creditManager);
return _deployLatestPatch({
contractType: AP_CREDIT_CONFIGURATOR,
minorVersion: version,
constructorParams: constructorParams,
salt: bytes32(bytes20(marketConfigurator))
});
}
function _deployCreditFacade(address marketConfigurator, address creditManager, CreditFacadeParams memory params)
internal
returns (address)
{
address contractsRegister = IMarketConfigurator(marketConfigurator).contractsRegister();
address lossPolicy = IContractsRegister(contractsRegister).getLossPolicy(ICreditManagerV3(creditManager).pool());
if (
params.degenNFT != address(0)
&& !IMarketConfigurator(marketConfigurator).isPeripheryContract(DOMAIN_DEGEN_NFT, params.degenNFT)
) {
revert DegenNFTIsNotRegisteredException(params.degenNFT);
}
address botList_ = botList;
if (params.migrateBotList) {
address prevCreditFacade = ICreditManagerV3(creditManager).creditFacade();
botList_ = ICreditFacadeV3(prevCreditFacade).botList();
}
address weth = _getAddress(AP_WETH_TOKEN, NO_VERSION_CONTROL);
bytes memory constructorParams =
abi.encode(addressProvider, creditManager, lossPolicy, botList_, weth, params.degenNFT, params.expirable);
return _deployLatestPatch({
contractType: AP_CREDIT_FACADE,
minorVersion: version,
constructorParams: constructorParams,
salt: bytes32(bytes20(marketConfigurator))
});
}
function _deployAdapter(address marketConfigurator, address creditManager, DeployParams memory params)
internal
returns (address)
{
address decodedCreditManager = abi.decode(params.constructorParams, (address));
if (decodedCreditManager != creditManager) revert InvalidConstructorParamsException();
return _deployLatestPatch({
contractType: _getContractType(DOMAIN_ADAPTER, params.postfix),
minorVersion: version,
constructorParams: params.constructorParams,
salt: keccak256(abi.encode(params.salt, marketConfigurator))
});
}
function _creditConfigurator(address creditManager) internal view returns (address) {
return ICreditManagerV3(creditManager).creditConfigurator();
}
function _creditFacade(address creditManager) internal view returns (address) {
return ICreditManagerV3(creditManager).creditFacade();
}
function _upgradeCreditConfigurator(address creditConfigurator, address newCreditConfigurator)
internal
pure
returns (Call memory)
{
return Call(
creditConfigurator, abi.encodeCall(ICreditConfiguratorV3.upgradeCreditConfigurator, (newCreditConfigurator))
);
}
function _setCreditFacade(address creditConfigurator, address creditFacade, bool migrateParams)
internal
pure
returns (Call memory)
{
return Call(
creditConfigurator, abi.encodeCall(ICreditConfiguratorV3.setCreditFacade, (creditFacade, migrateParams))
);
}
function _setPriceOracle(address creditConfigurator, address priceOracle) internal pure returns (Call memory) {
return Call(creditConfigurator, abi.encodeCall(ICreditConfiguratorV3.setPriceOracle, priceOracle));
}
function _setLossPolicy(address creditConfigurator, address lossPolicy) internal pure returns (Call memory) {
return Call(creditConfigurator, abi.encodeCall(ICreditConfiguratorV3.setLossPolicy, lossPolicy));
}
function _allowAdapter(address creditConfigurator, address adapter) internal pure returns (Call memory) {
return Call(creditConfigurator, abi.encodeCall(ICreditConfiguratorV3.allowAdapter, adapter));
}
function _forbidAdapter(address creditConfigurator, address adapter) internal pure returns (Call memory) {
return Call(creditConfigurator, abi.encodeCall(ICreditConfiguratorV3.forbidAdapter, adapter));
}
function _setDebtLimits(address creditConfigurator, uint128 minDebt, uint128 maxDebt)
internal
pure
returns (Call memory)
{
return Call(creditConfigurator, abi.encodeCall(ICreditConfiguratorV3.setDebtLimits, (minDebt, maxDebt)));
}
function _makeAllTokensQuoted(address creditConfigurator) internal pure returns (Call memory) {
return Call(creditConfigurator, abi.encodeCall(ICreditConfiguratorV3.makeAllTokensQuoted, ()));
}
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
struct AddressProviderEntry {
bytes32 key;
uint256 ver;
address value;
}
struct AuditReport {
address auditor;
string reportUrl;
bytes signature;
}
struct Bytecode {
bytes32 contractType;
uint256 version;
bytes initCode;
address author;
string source;
bytes authorSignature;
}
struct BytecodePointer {
bytes32 contractType;
uint256 version;
address[] initCodePointers;
address author;
string source;
bytes authorSignature;
}
struct Call {
address target;
bytes callData;
}
struct ConnectedPriceFeed {
address token;
address[] priceFeeds;
}
struct CrossChainCall {
uint256 chainId; // 0 means to be executed on all chains
address target;
bytes callData;
}
struct DeployParams {
bytes32 postfix;
bytes32 salt;
bytes constructorParams;
}
struct DeployResult {
address newContract;
Call[] onInstallOps;
}
struct MarketFactories {
address poolFactory;
address priceOracleFactory;
address interestRateModelFactory;
address rateKeeperFactory;
address lossPolicyFactory;
}
struct PriceFeedInfo {
string name;
uint32 stalenessPeriod;
bytes32 priceFeedType;
uint256 version;
}
struct SignedBatch {
string name;
bytes32 prevHash;
CrossChainCall[] calls;
bytes[] signatures;
}
struct SignedRecoveryModeMessage {
uint256 chainId;
bytes32 startingBatchHash;
bytes[] signatures;
}
struct Split {
bool initialized;
address[] receivers;
uint16[] proportions;
}
struct TwoAdminProposal {
bytes callData;
bool confirmedByAdmin;
bool confirmedByTreasuryProxy;
}// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {LibString} from "@solady/utils/LibString.sol";
library Domain {
using LibString for string;
using LibString for bytes32;
uint128 internal constant UNDERSCORE = 1 << 95;
function getContractType(bytes32 domain, bytes32 postfix) internal pure returns (bytes32) {
if (postfix == 0) return domain;
return string.concat(domain.fromSmallString(), "::", postfix.fromSmallString()).toSmallString();
}
function extractDomain(bytes32 contractType) internal pure returns (bytes32) {
string memory str = contractType.fromSmallString();
uint256 separatorIndex = str.indexOf("::");
// If no separator found, treat the whole type as domain
if (separatorIndex == LibString.NOT_FOUND) return str.toSmallString();
return str.slice(0, separatorIndex).toSmallString();
}
function extractPostfix(bytes32 contractType) internal pure returns (bytes32) {
string memory str = contractType.fromSmallString();
uint256 separatorIndex = str.indexOf("::");
// if no separator found, return empty postfix
if (separatorIndex == LibString.NOT_FOUND) return bytes32(0);
return str.slice(separatorIndex + 2).toSmallString();
}
function isValidContractType(bytes32 contractType) internal pure returns (bool) {
bytes32 domain = extractDomain(contractType);
if (!isValidDomain(domain)) return false;
bytes32 postfix = extractPostfix(contractType);
if (!isValidPostfix(postfix)) return false;
// avoid the "DOMAIN::" case
return contractType == getContractType(domain, postfix);
}
function isValidDomain(bytes32 domain) internal pure returns (bool) {
return domain != 0 && _isValidString(domain.fromSmallString());
}
function isValidPostfix(bytes32 postfix) internal pure returns (bool) {
return _isValidString(postfix.fromSmallString());
}
function _isValidString(string memory str) internal pure returns (bool) {
return str.is7BitASCII(LibString.ALPHANUMERIC_7_BIT_ASCII | UNDERSCORE);
}
}// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {LibString} from "@solady/utils/LibString.sol";
import {IAddressProvider} from "../interfaces/IAddressProvider.sol";
import {IBytecodeRepository} from "../interfaces/IBytecodeRepository.sol";
import {IDeployerTrait} from "../interfaces/base/IDeployerTrait.sol";
import {AP_BYTECODE_REPOSITORY, NO_VERSION_CONTROL} from "../libraries/ContractLiterals.sol";
import {Domain} from "../libraries/Domain.sol";
abstract contract DeployerTrait is IDeployerTrait {
using LibString for string;
using LibString for bytes32;
address public immutable override addressProvider;
address public immutable override bytecodeRepository;
constructor(address addressProvider_) {
addressProvider = addressProvider_;
bytecodeRepository = _getAddressOrRevert(AP_BYTECODE_REPOSITORY, NO_VERSION_CONTROL);
}
function _getAddress(bytes32 key, uint256 version) internal view returns (address) {
return IAddressProvider(addressProvider).getAddress(key, version);
}
function _getAddressOrRevert(bytes32 key, uint256 version) internal view returns (address) {
return IAddressProvider(addressProvider).getAddressOrRevert(key, version);
}
function _getContractType(bytes32 domain, bytes32 postfix) internal pure returns (bytes32) {
return Domain.getContractType(domain, postfix);
}
function _deploy(bytes32 contractType, uint256 version, bytes memory constructorParams, bytes32 salt)
internal
returns (address)
{
return IBytecodeRepository(bytecodeRepository).deploy(contractType, version, constructorParams, salt);
}
function _computeAddress(
bytes32 contractType,
uint256 version,
bytes memory constructorParams,
bytes32 salt,
address deployer
) internal view returns (address) {
return IBytecodeRepository(bytecodeRepository).computeAddress(
contractType, version, constructorParams, salt, deployer
);
}
function _deployLatestPatch(
bytes32 contractType,
uint256 minorVersion,
bytes memory constructorParams,
bytes32 salt
) internal returns (address) {
// NOTE: it's best to add a check that deployed contract's version matches the expected one in the governor
return _deploy(contractType, _getLatestPatchVersion(contractType, minorVersion), constructorParams, salt);
}
function _computeAddressLatestPatch(
bytes32 contractType,
uint256 minorVersion,
bytes memory constructorParams,
bytes32 salt,
address deployer
) internal view returns (address) {
return _computeAddress(
contractType, _getLatestPatchVersion(contractType, minorVersion), constructorParams, salt, deployer
);
}
function _getLatestPatchVersion(bytes32 contractType, uint256 minorVersion) internal view returns (uint256) {
return IBytecodeRepository(bytecodeRepository).getLatestPatchVersion(contractType, minorVersion);
}
function _getTokenSpecificPostfix(address token) internal view returns (bytes32) {
return IBytecodeRepository(bytecodeRepository).getTokenSpecificPostfix(token);
}
}// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {Call} from "../interfaces/Types.sol";
library CallBuilder {
function build() internal pure returns (Call[] memory calls) {}
function build(Call memory call1) internal pure returns (Call[] memory calls) {
calls = new Call[](1);
calls[0] = call1;
}
function build(Call memory call1, Call memory call2) internal pure returns (Call[] memory calls) {
calls = new Call[](2);
calls[0] = call1;
calls[1] = call2;
}
function build(Call memory call1, Call memory call2, Call memory call3)
internal
pure
returns (Call[] memory calls)
{
calls = new Call[](3);
calls[0] = call1;
calls[1] = call2;
calls[2] = call3;
}
function build(Call memory call1, Call memory call2, Call memory call3, Call memory call4)
internal
pure
returns (Call[] memory calls)
{
calls = new Call[](4);
calls[0] = call1;
calls[1] = call2;
calls[2] = call3;
calls[3] = call4;
}
function build(Call memory call1, Call memory call2, Call memory call3, Call memory call4, Call memory call5)
internal
pure
returns (Call[] memory calls)
{
calls = new Call[](5);
calls[0] = call1;
calls[1] = call2;
calls[2] = call3;
calls[3] = call4;
calls[4] = call5;
}
function build(
Call memory call1,
Call memory call2,
Call memory call3,
Call memory call4,
Call memory call5,
Call memory call6
) internal pure returns (Call[] memory calls) {
calls = new Call[](6);
calls[0] = call1;
calls[1] = call2;
calls[2] = call3;
calls[3] = call4;
calls[4] = call5;
calls[5] = call6;
}
function append(Call[] memory calls, Call memory call) internal pure returns (Call[] memory newCalls) {
uint256 numCalls = calls.length;
newCalls = new Call[](numCalls + 1);
for (uint256 i; i < numCalls; ++i) {
newCalls[i] = calls[i];
}
newCalls[numCalls] = call;
}
function extend(Call[] memory calls1, Call[] memory calls2) internal pure returns (Call[] memory newCalls) {
uint256 num1 = calls1.length;
uint256 num2 = calls2.length;
newCalls = new Call[](num1 + num2);
for (uint256 i; i < num1; ++i) {
newCalls[i] = calls1[i];
}
for (uint256 i; i < num2; ++i) {
newCalls[num1 + i] = calls2[i];
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Library for converting numbers into strings and other string operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
///
/// @dev Note:
/// For performance and bytecode compactness, most of the string operations are restricted to
/// byte strings (7-bit ASCII), except where otherwise specified.
/// Usage of byte string operations on charsets with runes spanning two or more bytes
/// can lead to undefined behavior.
library LibString {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The length of the output is too small to contain all the hex digits.
error HexLengthInsufficient();
/// @dev The length of the string is more than 32 bytes.
error TooBigForSmallString();
/// @dev The input string must be a 7-bit ASCII.
error StringNot7BitASCII();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The constant returned when the `search` is not found in the string.
uint256 internal constant NOT_FOUND = type(uint256).max;
/// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.
uint128 internal constant ALPHANUMERIC_7_BIT_ASCII = 0x7fffffe07fffffe03ff000000000000;
/// @dev Lookup for 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.
uint128 internal constant LETTERS_7_BIT_ASCII = 0x7fffffe07fffffe0000000000000000;
/// @dev Lookup for 'abcdefghijklmnopqrstuvwxyz'.
uint128 internal constant LOWERCASE_7_BIT_ASCII = 0x7fffffe000000000000000000000000;
/// @dev Lookup for 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
uint128 internal constant UPPERCASE_7_BIT_ASCII = 0x7fffffe0000000000000000;
/// @dev Lookup for '0123456789'.
uint128 internal constant DIGITS_7_BIT_ASCII = 0x3ff000000000000;
/// @dev Lookup for '0123456789abcdefABCDEF'.
uint128 internal constant HEXDIGITS_7_BIT_ASCII = 0x7e0000007e03ff000000000000;
/// @dev Lookup for '01234567'.
uint128 internal constant OCTDIGITS_7_BIT_ASCII = 0xff000000000000;
/// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'.
uint128 internal constant PRINTABLE_7_BIT_ASCII = 0x7fffffffffffffffffffffff00003e00;
/// @dev Lookup for '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'.
uint128 internal constant PUNCTUATION_7_BIT_ASCII = 0x78000001f8000001fc00fffe00000000;
/// @dev Lookup for ' \t\n\r\x0b\x0c'.
uint128 internal constant WHITESPACE_7_BIT_ASCII = 0x100003e00;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* DECIMAL OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the base 10 decimal representation of `value`.
function toString(uint256 value) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
// The maximum value of a uint256 contains 78 digits (1 byte per digit), but
// we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
// We will need 1 word for the trailing zeros padding, 1 word for the length,
// and 3 words for a maximum of 78 digits.
str := add(mload(0x40), 0x80)
// Update the free memory pointer to allocate.
mstore(0x40, add(str, 0x20))
// Zeroize the slot after the string.
mstore(str, 0)
// Cache the end of the memory to calculate the length later.
let end := str
let w := not(0) // Tsk.
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
for { let temp := value } 1 {} {
str := add(str, w) // `sub(str, 1)`.
// Write the character to the pointer.
// The ASCII index of the '0' character is 48.
mstore8(str, add(48, mod(temp, 10)))
// Keep dividing `temp` until zero.
temp := div(temp, 10)
if iszero(temp) { break }
}
let length := sub(end, str)
// Move the pointer 32 bytes leftwards to make room for the length.
str := sub(str, 0x20)
// Store the length.
mstore(str, length)
}
}
/// @dev Returns the base 10 decimal representation of `value`.
function toString(int256 value) internal pure returns (string memory str) {
if (value >= 0) {
return toString(uint256(value));
}
unchecked {
str = toString(~uint256(value) + 1);
}
/// @solidity memory-safe-assembly
assembly {
// We still have some spare memory space on the left,
// as we have allocated 3 words (96 bytes) for up to 78 digits.
let length := mload(str) // Load the string length.
mstore(str, 0x2d) // Store the '-' character.
str := sub(str, 1) // Move back the string pointer by a byte.
mstore(str, add(length, 1)) // Update the string length.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HEXADECIMAL OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the hexadecimal representation of `value`,
/// left-padded to an input length of `length` bytes.
/// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
/// giving a total length of `length * 2 + 2` bytes.
/// Reverts if `length` is too small for the output to contain all the digits.
function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value, length);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hexadecimal representation of `value`,
/// left-padded to an input length of `length` bytes.
/// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte,
/// giving a total length of `length * 2` bytes.
/// Reverts if `length` is too small for the output to contain all the digits.
function toHexStringNoPrefix(uint256 value, uint256 length)
internal
pure
returns (string memory str)
{
/// @solidity memory-safe-assembly
assembly {
// We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes
// for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length.
// We add 0x20 to the total and round down to a multiple of 0x20.
// (0x20 + 0x20 + 0x02 + 0x20) = 0x62.
str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f)))
// Allocate the memory.
mstore(0x40, add(str, 0x20))
// Zeroize the slot after the string.
mstore(str, 0)
// Cache the end to calculate the length later.
let end := str
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
let start := sub(str, add(length, length))
let w := not(1) // Tsk.
let temp := value
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
for {} 1 {} {
str := add(str, w) // `sub(str, 2)`.
mstore8(add(str, 1), mload(and(temp, 15)))
mstore8(str, mload(and(shr(4, temp), 15)))
temp := shr(8, temp)
if iszero(xor(str, start)) { break }
}
if temp {
mstore(0x00, 0x2194895a) // `HexLengthInsufficient()`.
revert(0x1c, 0x04)
}
// Compute the string's length.
let strLength := sub(end, str)
// Move the pointer and write the length.
str := sub(str, 0x20)
mstore(str, strLength)
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
/// As address are 20 bytes long, the output will left-padded to have
/// a length of `20 * 2 + 2` bytes.
function toHexString(uint256 value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x".
/// The output excludes leading "0" from the `toHexString` output.
/// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`.
function toMinimalHexString(uint256 value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
/// @solidity memory-safe-assembly
assembly {
let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.
let strLength := add(mload(str), 2) // Compute the length.
mstore(add(str, o), 0x3078) // Write the "0x" prefix, accounting for leading zero.
str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero.
mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero.
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output excludes leading "0" from the `toHexStringNoPrefix` output.
/// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`.
function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
/// @solidity memory-safe-assembly
assembly {
let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present.
let strLength := mload(str) // Get the length.
str := add(str, o) // Move the pointer, accounting for leading zero.
mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero.
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is encoded using 2 hexadecimal digits per byte.
/// As address are 20 bytes long, the output will left-padded to have
/// a length of `20 * 2` bytes.
function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
// We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
// 0x02 bytes for the prefix, and 0x40 bytes for the digits.
// The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0.
str := add(mload(0x40), 0x80)
// Allocate the memory.
mstore(0x40, add(str, 0x20))
// Zeroize the slot after the string.
mstore(str, 0)
// Cache the end to calculate the length later.
let end := str
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
let w := not(1) // Tsk.
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
for { let temp := value } 1 {} {
str := add(str, w) // `sub(str, 2)`.
mstore8(add(str, 1), mload(and(temp, 15)))
mstore8(str, mload(and(shr(4, temp), 15)))
temp := shr(8, temp)
if iszero(temp) { break }
}
// Compute the string's length.
let strLength := sub(end, str)
// Move the pointer and write the length.
str := sub(str, 0x20)
mstore(str, strLength)
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte,
/// and the alphabets are capitalized conditionally according to
/// https://eips.ethereum.org/EIPS/eip-55
function toHexStringChecksummed(address value) internal pure returns (string memory str) {
str = toHexString(value);
/// @solidity memory-safe-assembly
assembly {
let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...`
let o := add(str, 0x22)
let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... `
let t := shl(240, 136) // `0b10001000 << 240`
for { let i := 0 } 1 {} {
mstore(add(i, i), mul(t, byte(i, hashed)))
i := add(i, 1)
if eq(i, 20) { break }
}
mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask)))))
o := add(o, 0x20)
mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask)))))
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte.
function toHexString(address value) internal pure returns (string memory str) {
str = toHexStringNoPrefix(value);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hexadecimal representation of `value`.
/// The output is encoded using 2 hexadecimal digits per byte.
function toHexStringNoPrefix(address value) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
str := mload(0x40)
// Allocate the memory.
// We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length,
// 0x02 bytes for the prefix, and 0x28 bytes for the digits.
// The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80.
mstore(0x40, add(str, 0x80))
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
str := add(str, 2)
mstore(str, 40)
let o := add(str, 0x20)
mstore(add(o, 40), 0)
value := shl(96, value)
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
for { let i := 0 } 1 {} {
let p := add(o, add(i, i))
let temp := byte(i, value)
mstore8(add(p, 1), mload(and(temp, 15)))
mstore8(p, mload(shr(4, temp)))
i := add(i, 1)
if eq(i, 20) { break }
}
}
}
/// @dev Returns the hex encoded string from the raw bytes.
/// The output is encoded using 2 hexadecimal digits per byte.
function toHexString(bytes memory raw) internal pure returns (string memory str) {
str = toHexStringNoPrefix(raw);
/// @solidity memory-safe-assembly
assembly {
let strLength := add(mload(str), 2) // Compute the length.
mstore(str, 0x3078) // Write the "0x" prefix.
str := sub(str, 2) // Move the pointer.
mstore(str, strLength) // Write the length.
}
}
/// @dev Returns the hex encoded string from the raw bytes.
/// The output is encoded using 2 hexadecimal digits per byte.
function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
let length := mload(raw)
str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix.
mstore(str, add(length, length)) // Store the length of the output.
// Store "0123456789abcdef" in scratch space.
mstore(0x0f, 0x30313233343536373839616263646566)
let o := add(str, 0x20)
let end := add(raw, length)
for {} iszero(eq(raw, end)) {} {
raw := add(raw, 1)
mstore8(add(o, 1), mload(and(mload(raw), 15)))
mstore8(o, mload(and(shr(4, mload(raw)), 15)))
o := add(o, 2)
}
mstore(o, 0) // Zeroize the slot after the string.
mstore(0x40, add(o, 0x20)) // Allocate the memory.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RUNE STRING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the number of UTF characters in the string.
function runeCount(string memory s) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
if mload(s) {
mstore(0x00, div(not(0), 255))
mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506)
let o := add(s, 0x20)
let end := add(o, mload(s))
for { result := 1 } 1 { result := add(result, 1) } {
o := add(o, byte(0, mload(shr(250, mload(o)))))
if iszero(lt(o, end)) { break }
}
}
}
}
/// @dev Returns if this string is a 7-bit ASCII string.
/// (i.e. all characters codes are in [0..127])
function is7BitASCII(string memory s) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
let mask := shl(7, div(not(0), 255))
result := 1
let n := mload(s)
if n {
let o := add(s, 0x20)
let end := add(o, n)
let last := mload(end)
mstore(end, 0)
for {} 1 {} {
if and(mask, mload(o)) {
result := 0
break
}
o := add(o, 0x20)
if iszero(lt(o, end)) { break }
}
mstore(end, last)
}
}
}
/// @dev Returns if this string is a 7-bit ASCII string,
/// AND all characters are in the `allowed` lookup.
/// Note: If `s` is empty, returns true regardless of `allowed`.
function is7BitASCII(string memory s, uint128 allowed) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := 1
if mload(s) {
let allowed_ := shr(128, shl(128, allowed))
let o := add(s, 0x20)
let end := add(o, mload(s))
for {} 1 {} {
result := and(result, shr(byte(0, mload(o)), allowed_))
o := add(o, 1)
if iszero(and(result, lt(o, end))) { break }
}
}
}
}
/// @dev Converts the bytes in the 7-bit ASCII string `s` to
/// an allowed lookup for use in `is7BitASCII(s, allowed)`.
/// To save runtime gas, you can cache the result in an immutable variable.
function to7BitASCIIAllowedLookup(string memory s) internal pure returns (uint128 result) {
/// @solidity memory-safe-assembly
assembly {
if mload(s) {
let o := add(s, 0x20)
let end := add(o, mload(s))
for {} 1 {} {
result := or(result, shl(byte(0, mload(o)), 1))
o := add(o, 1)
if iszero(lt(o, end)) { break }
}
if shr(128, result) {
mstore(0x00, 0xc9807e0d) // `StringNot7BitASCII()`.
revert(0x1c, 0x04)
}
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BYTE STRING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// For performance and bytecode compactness, byte string operations are restricted
// to 7-bit ASCII strings. All offsets are byte offsets, not UTF character offsets.
// Usage of byte string operations on charsets with runes spanning two or more bytes
// can lead to undefined behavior.
/// @dev Returns `subject` all occurrences of `search` replaced with `replacement`.
function replace(string memory subject, string memory search, string memory replacement)
internal
pure
returns (string memory result)
{
/// @solidity memory-safe-assembly
assembly {
let subjectLength := mload(subject)
let searchLength := mload(search)
let replacementLength := mload(replacement)
subject := add(subject, 0x20)
search := add(search, 0x20)
replacement := add(replacement, 0x20)
result := add(mload(0x40), 0x20)
let subjectEnd := add(subject, subjectLength)
if iszero(gt(searchLength, subjectLength)) {
let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1)
let h := 0
if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
let s := mload(search)
for {} 1 {} {
let t := mload(subject)
// Whether the first `searchLength % 32` bytes of
// `subject` and `search` matches.
if iszero(shr(m, xor(t, s))) {
if h {
if iszero(eq(keccak256(subject, searchLength), h)) {
mstore(result, t)
result := add(result, 1)
subject := add(subject, 1)
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
// Copy the `replacement` one word at a time.
for { let o := 0 } 1 {} {
mstore(add(result, o), mload(add(replacement, o)))
o := add(o, 0x20)
if iszero(lt(o, replacementLength)) { break }
}
result := add(result, replacementLength)
subject := add(subject, searchLength)
if searchLength {
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
mstore(result, t)
result := add(result, 1)
subject := add(subject, 1)
if iszero(lt(subject, subjectSearchEnd)) { break }
}
}
let resultRemainder := result
result := add(mload(0x40), 0x20)
let k := add(sub(resultRemainder, result), sub(subjectEnd, subject))
// Copy the rest of the string one word at a time.
for {} lt(subject, subjectEnd) {} {
mstore(resultRemainder, mload(subject))
resultRemainder := add(resultRemainder, 0x20)
subject := add(subject, 0x20)
}
result := sub(result, 0x20)
let last := add(add(result, 0x20), k) // Zeroize the slot after the string.
mstore(last, 0)
mstore(0x40, add(last, 0x20)) // Allocate the memory.
mstore(result, k) // Store the length.
}
}
/// @dev Returns the byte index of the first location of `search` in `subject`,
/// searching from left to right, starting from `from`.
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
function indexOf(string memory subject, string memory search, uint256 from)
internal
pure
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
for { let subjectLength := mload(subject) } 1 {} {
if iszero(mload(search)) {
if iszero(gt(from, subjectLength)) {
result := from
break
}
result := subjectLength
break
}
let searchLength := mload(search)
let subjectStart := add(subject, 0x20)
result := not(0) // Initialize to `NOT_FOUND`.
subject := add(subjectStart, from)
let end := add(sub(add(subjectStart, subjectLength), searchLength), 1)
let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
let s := mload(add(search, 0x20))
if iszero(and(lt(subject, end), lt(from, subjectLength))) { break }
if iszero(lt(searchLength, 0x20)) {
for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
if iszero(shr(m, xor(mload(subject), s))) {
if eq(keccak256(subject, searchLength), h) {
result := sub(subject, subjectStart)
break
}
}
subject := add(subject, 1)
if iszero(lt(subject, end)) { break }
}
break
}
for {} 1 {} {
if iszero(shr(m, xor(mload(subject), s))) {
result := sub(subject, subjectStart)
break
}
subject := add(subject, 1)
if iszero(lt(subject, end)) { break }
}
break
}
}
}
/// @dev Returns the byte index of the first location of `search` in `subject`,
/// searching from left to right.
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
function indexOf(string memory subject, string memory search)
internal
pure
returns (uint256 result)
{
result = indexOf(subject, search, 0);
}
/// @dev Returns the byte index of the first location of `search` in `subject`,
/// searching from right to left, starting from `from`.
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
function lastIndexOf(string memory subject, string memory search, uint256 from)
internal
pure
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
for {} 1 {} {
result := not(0) // Initialize to `NOT_FOUND`.
let searchLength := mload(search)
if gt(searchLength, mload(subject)) { break }
let w := result
let fromMax := sub(mload(subject), searchLength)
if iszero(gt(fromMax, from)) { from := fromMax }
let end := add(add(subject, 0x20), w)
subject := add(add(subject, 0x20), from)
if iszero(gt(subject, end)) { break }
// As this function is not too often used,
// we shall simply use keccak256 for smaller bytecode size.
for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} {
if eq(keccak256(subject, searchLength), h) {
result := sub(subject, add(end, 1))
break
}
subject := add(subject, w) // `sub(subject, 1)`.
if iszero(gt(subject, end)) { break }
}
break
}
}
}
/// @dev Returns the byte index of the first location of `search` in `subject`,
/// searching from right to left.
/// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found.
function lastIndexOf(string memory subject, string memory search)
internal
pure
returns (uint256 result)
{
result = lastIndexOf(subject, search, uint256(int256(-1)));
}
/// @dev Returns true if `search` is found in `subject`, false otherwise.
function contains(string memory subject, string memory search) internal pure returns (bool) {
return indexOf(subject, search) != NOT_FOUND;
}
/// @dev Returns whether `subject` starts with `search`.
function startsWith(string memory subject, string memory search)
internal
pure
returns (bool result)
{
/// @solidity memory-safe-assembly
assembly {
let searchLength := mload(search)
// Just using keccak256 directly is actually cheaper.
// forgefmt: disable-next-item
result := and(
iszero(gt(searchLength, mload(subject))),
eq(
keccak256(add(subject, 0x20), searchLength),
keccak256(add(search, 0x20), searchLength)
)
)
}
}
/// @dev Returns whether `subject` ends with `search`.
function endsWith(string memory subject, string memory search)
internal
pure
returns (bool result)
{
/// @solidity memory-safe-assembly
assembly {
let searchLength := mload(search)
let subjectLength := mload(subject)
// Whether `search` is not longer than `subject`.
let withinRange := iszero(gt(searchLength, subjectLength))
// Just using keccak256 directly is actually cheaper.
// forgefmt: disable-next-item
result := and(
withinRange,
eq(
keccak256(
// `subject + 0x20 + max(subjectLength - searchLength, 0)`.
add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))),
searchLength
),
keccak256(add(search, 0x20), searchLength)
)
)
}
}
/// @dev Returns `subject` repeated `times`.
function repeat(string memory subject, uint256 times)
internal
pure
returns (string memory result)
{
/// @solidity memory-safe-assembly
assembly {
let subjectLength := mload(subject)
if iszero(or(iszero(times), iszero(subjectLength))) {
subject := add(subject, 0x20)
result := mload(0x40)
let output := add(result, 0x20)
for {} 1 {} {
// Copy the `subject` one word at a time.
for { let o := 0 } 1 {} {
mstore(add(output, o), mload(add(subject, o)))
o := add(o, 0x20)
if iszero(lt(o, subjectLength)) { break }
}
output := add(output, subjectLength)
times := sub(times, 1)
if iszero(times) { break }
}
mstore(output, 0) // Zeroize the slot after the string.
let resultLength := sub(output, add(result, 0x20))
mstore(result, resultLength) // Store the length.
// Allocate the memory.
mstore(0x40, add(result, add(resultLength, 0x20)))
}
}
}
/// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function slice(string memory subject, uint256 start, uint256 end)
internal
pure
returns (string memory result)
{
/// @solidity memory-safe-assembly
assembly {
let subjectLength := mload(subject)
if iszero(gt(subjectLength, end)) { end := subjectLength }
if iszero(gt(subjectLength, start)) { start := subjectLength }
if lt(start, end) {
result := mload(0x40)
let resultLength := sub(end, start)
mstore(result, resultLength)
subject := add(subject, start)
let w := not(0x1f)
// Copy the `subject` one word at a time, backwards.
for { let o := and(add(resultLength, 0x1f), w) } 1 {} {
mstore(add(result, o), mload(add(subject, o)))
o := add(o, w) // `sub(o, 0x20)`.
if iszero(o) { break }
}
// Zeroize the slot after the string.
mstore(add(add(result, 0x20), resultLength), 0)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, add(result, and(add(resultLength, 0x3f), w)))
}
}
}
/// @dev Returns a copy of `subject` sliced from `start` to the end of the string.
/// `start` is a byte offset.
function slice(string memory subject, uint256 start)
internal
pure
returns (string memory result)
{
result = slice(subject, start, uint256(int256(-1)));
}
/// @dev Returns all the indices of `search` in `subject`.
/// The indices are byte offsets.
function indicesOf(string memory subject, string memory search)
internal
pure
returns (uint256[] memory result)
{
/// @solidity memory-safe-assembly
assembly {
let subjectLength := mload(subject)
let searchLength := mload(search)
if iszero(gt(searchLength, subjectLength)) {
subject := add(subject, 0x20)
search := add(search, 0x20)
result := add(mload(0x40), 0x20)
let subjectStart := subject
let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1)
let h := 0
if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) }
let m := shl(3, sub(0x20, and(searchLength, 0x1f)))
let s := mload(search)
for {} 1 {} {
let t := mload(subject)
// Whether the first `searchLength % 32` bytes of
// `subject` and `search` matches.
if iszero(shr(m, xor(t, s))) {
if h {
if iszero(eq(keccak256(subject, searchLength), h)) {
subject := add(subject, 1)
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
// Append to `result`.
mstore(result, sub(subject, subjectStart))
result := add(result, 0x20)
// Advance `subject` by `searchLength`.
subject := add(subject, searchLength)
if searchLength {
if iszero(lt(subject, subjectSearchEnd)) { break }
continue
}
}
subject := add(subject, 1)
if iszero(lt(subject, subjectSearchEnd)) { break }
}
let resultEnd := result
// Assign `result` to the free memory pointer.
result := mload(0x40)
// Store the length of `result`.
mstore(result, shr(5, sub(resultEnd, add(result, 0x20))))
// Allocate memory for result.
// We allocate one more word, so this array can be recycled for {split}.
mstore(0x40, add(resultEnd, 0x20))
}
}
}
/// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string.
function split(string memory subject, string memory delimiter)
internal
pure
returns (string[] memory result)
{
uint256[] memory indices = indicesOf(subject, delimiter);
/// @solidity memory-safe-assembly
assembly {
let w := not(0x1f)
let indexPtr := add(indices, 0x20)
let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1)))
mstore(add(indicesEnd, w), mload(subject))
mstore(indices, add(mload(indices), 1))
let prevIndex := 0
for {} 1 {} {
let index := mload(indexPtr)
mstore(indexPtr, 0x60)
if iszero(eq(index, prevIndex)) {
let element := mload(0x40)
let elementLength := sub(index, prevIndex)
mstore(element, elementLength)
// Copy the `subject` one word at a time, backwards.
for { let o := and(add(elementLength, 0x1f), w) } 1 {} {
mstore(add(element, o), mload(add(add(subject, prevIndex), o)))
o := add(o, w) // `sub(o, 0x20)`.
if iszero(o) { break }
}
// Zeroize the slot after the string.
mstore(add(add(element, 0x20), elementLength), 0)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, add(element, and(add(elementLength, 0x3f), w)))
// Store the `element` into the array.
mstore(indexPtr, element)
}
prevIndex := add(index, mload(delimiter))
indexPtr := add(indexPtr, 0x20)
if iszero(lt(indexPtr, indicesEnd)) { break }
}
result := indices
if iszero(mload(delimiter)) {
result := add(indices, 0x20)
mstore(result, sub(mload(indices), 2))
}
}
}
/// @dev Returns a concatenated string of `a` and `b`.
/// Cheaper than `string.concat()` and does not de-align the free memory pointer.
function concat(string memory a, string memory b)
internal
pure
returns (string memory result)
{
/// @solidity memory-safe-assembly
assembly {
let w := not(0x1f)
result := mload(0x40)
let aLength := mload(a)
// Copy `a` one word at a time, backwards.
for { let o := and(add(aLength, 0x20), w) } 1 {} {
mstore(add(result, o), mload(add(a, o)))
o := add(o, w) // `sub(o, 0x20)`.
if iszero(o) { break }
}
let bLength := mload(b)
let output := add(result, aLength)
// Copy `b` one word at a time, backwards.
for { let o := and(add(bLength, 0x20), w) } 1 {} {
mstore(add(output, o), mload(add(b, o)))
o := add(o, w) // `sub(o, 0x20)`.
if iszero(o) { break }
}
let totalLength := add(aLength, bLength)
let last := add(add(result, 0x20), totalLength)
// Zeroize the slot after the string.
mstore(last, 0)
// Stores the length.
mstore(result, totalLength)
// Allocate memory for the length and the bytes,
// rounded up to a multiple of 32.
mstore(0x40, and(add(last, 0x1f), w))
}
}
/// @dev Returns a copy of the string in either lowercase or UPPERCASE.
/// WARNING! This function is only compatible with 7-bit ASCII strings.
function toCase(string memory subject, bool toUpper)
internal
pure
returns (string memory result)
{
/// @solidity memory-safe-assembly
assembly {
let length := mload(subject)
if length {
result := add(mload(0x40), 0x20)
subject := add(subject, 1)
let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff)
let w := not(0)
for { let o := length } 1 {} {
o := add(o, w)
let b := and(0xff, mload(add(subject, o)))
mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20)))
if iszero(o) { break }
}
result := mload(0x40)
mstore(result, length) // Store the length.
let last := add(add(result, 0x20), length)
mstore(last, 0) // Zeroize the slot after the string.
mstore(0x40, add(last, 0x20)) // Allocate the memory.
}
}
}
/// @dev Returns a string from a small bytes32 string.
/// `s` must be null-terminated, or behavior will be undefined.
function fromSmallString(bytes32 s) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(0x40)
let n := 0
for {} byte(n, s) { n := add(n, 1) } {} // Scan for '\0'.
mstore(result, n)
let o := add(result, 0x20)
mstore(o, s)
mstore(add(o, n), 0)
mstore(0x40, add(result, 0x40))
}
}
/// @dev Returns the small string, with all bytes after the first null byte zeroized.
function normalizeSmallString(bytes32 s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
for {} byte(result, s) { result := add(result, 1) } {} // Scan for '\0'.
mstore(0x00, s)
mstore(result, 0x00)
result := mload(0x00)
}
}
/// @dev Returns the string as a normalized null-terminated small string.
function toSmallString(string memory s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(s)
if iszero(lt(result, 33)) {
mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`.
revert(0x1c, 0x04)
}
result := shl(shl(3, sub(32, result)), mload(add(s, result)))
}
}
/// @dev Returns a lowercased copy of the string.
/// WARNING! This function is only compatible with 7-bit ASCII strings.
function lower(string memory subject) internal pure returns (string memory result) {
result = toCase(subject, false);
}
/// @dev Returns an UPPERCASED copy of the string.
/// WARNING! This function is only compatible with 7-bit ASCII strings.
function upper(string memory subject) internal pure returns (string memory result) {
result = toCase(subject, true);
}
/// @dev Escapes the string to be used within HTML tags.
function escapeHTML(string memory s) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
let end := add(s, mload(s))
result := add(mload(0x40), 0x20)
// Store the bytes of the packed offsets and strides into the scratch space.
// `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6.
mstore(0x1f, 0x900094)
mstore(0x08, 0xc0000000a6ab)
// Store ""&'<>" into the scratch space.
mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b))
for {} iszero(eq(s, end)) {} {
s := add(s, 1)
let c := and(mload(s), 0xff)
// Not in `["\"","'","&","<",">"]`.
if iszero(and(shl(c, 1), 0x500000c400000000)) {
mstore8(result, c)
result := add(result, 1)
continue
}
let t := shr(248, mload(c))
mstore(result, mload(and(t, 0x1f)))
result := add(result, shr(5, t))
}
let last := result
mstore(last, 0) // Zeroize the slot after the string.
result := mload(0x40)
mstore(result, sub(last, add(result, 0x20))) // Store the length.
mstore(0x40, add(last, 0x20)) // Allocate the memory.
}
}
/// @dev Escapes the string to be used within double-quotes in a JSON.
/// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes.
function escapeJSON(string memory s, bool addDoubleQuotes)
internal
pure
returns (string memory result)
{
/// @solidity memory-safe-assembly
assembly {
let end := add(s, mload(s))
result := add(mload(0x40), 0x20)
if addDoubleQuotes {
mstore8(result, 34)
result := add(1, result)
}
// Store "\\u0000" in scratch space.
// Store "0123456789abcdef" in scratch space.
// Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`.
// into the scratch space.
mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672)
// Bitmask for detecting `["\"","\\"]`.
let e := or(shl(0x22, 1), shl(0x5c, 1))
for {} iszero(eq(s, end)) {} {
s := add(s, 1)
let c := and(mload(s), 0xff)
if iszero(lt(c, 0x20)) {
if iszero(and(shl(c, 1), e)) {
// Not in `["\"","\\"]`.
mstore8(result, c)
result := add(result, 1)
continue
}
mstore8(result, 0x5c) // "\\".
mstore8(add(result, 1), c)
result := add(result, 2)
continue
}
if iszero(and(shl(c, 1), 0x3700)) {
// Not in `["\b","\t","\n","\f","\d"]`.
mstore8(0x1d, mload(shr(4, c))) // Hex value.
mstore8(0x1e, mload(and(c, 15))) // Hex value.
mstore(result, mload(0x19)) // "\\u00XX".
result := add(result, 6)
continue
}
mstore8(result, 0x5c) // "\\".
mstore8(add(result, 1), mload(add(c, 8)))
result := add(result, 2)
}
if addDoubleQuotes {
mstore8(result, 34)
result := add(1, result)
}
let last := result
mstore(last, 0) // Zeroize the slot after the string.
result := mload(0x40)
mstore(result, sub(last, add(result, 0x20))) // Store the length.
mstore(0x40, add(last, 0x20)) // Allocate the memory.
}
}
/// @dev Escapes the string to be used within double-quotes in a JSON.
function escapeJSON(string memory s) internal pure returns (string memory result) {
result = escapeJSON(s, false);
}
/// @dev Returns whether `a` equals `b`.
function eq(string memory a, string memory b) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b)))
}
}
/// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small string.
function eqs(string memory a, bytes32 b) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
// These should be evaluated on compile time, as far as possible.
let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`.
let x := not(or(m, or(b, add(m, and(b, m)))))
let r := shl(7, iszero(iszero(shr(128, x))))
r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
// forgefmt: disable-next-item
result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))),
xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20)))))
}
}
/// @dev Packs a single string with its length into a single word.
/// Returns `bytes32(0)` if the length is zero or greater than 31.
function packOne(string memory a) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
// We don't need to zero right pad the string,
// since this is our own custom non-standard packing scheme.
result :=
mul(
// Load the length and the bytes.
mload(add(a, 0x1f)),
// `length != 0 && length < 32`. Abuses underflow.
// Assumes that the length is valid and within the block gas limit.
lt(sub(mload(a), 1), 0x1f)
)
}
}
/// @dev Unpacks a string packed using {packOne}.
/// Returns the empty string if `packed` is `bytes32(0)`.
/// If `packed` is not an output of {packOne}, the output behavior is undefined.
function unpackOne(bytes32 packed) internal pure returns (string memory result) {
/// @solidity memory-safe-assembly
assembly {
// Grab the free memory pointer.
result := mload(0x40)
// Allocate 2 words (1 for the length, 1 for the bytes).
mstore(0x40, add(result, 0x40))
// Zeroize the length slot.
mstore(result, 0)
// Store the length and bytes.
mstore(add(result, 0x1f), packed)
// Right pad with zeroes.
mstore(add(add(result, 0x20), mload(result)), 0)
}
}
/// @dev Packs two strings with their lengths into a single word.
/// Returns `bytes32(0)` if combined length is zero or greater than 30.
function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let aLength := mload(a)
// We don't need to zero right pad the strings,
// since this is our own custom non-standard packing scheme.
result :=
mul(
// Load the length and the bytes of `a` and `b`.
or(
shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))),
mload(sub(add(b, 0x1e), aLength))
),
// `totalLength != 0 && totalLength < 31`. Abuses underflow.
// Assumes that the lengths are valid and within the block gas limit.
lt(sub(add(aLength, mload(b)), 1), 0x1e)
)
}
}
/// @dev Unpacks strings packed using {packTwo}.
/// Returns the empty strings if `packed` is `bytes32(0)`.
/// If `packed` is not an output of {packTwo}, the output behavior is undefined.
function unpackTwo(bytes32 packed)
internal
pure
returns (string memory resultA, string memory resultB)
{
/// @solidity memory-safe-assembly
assembly {
// Grab the free memory pointer.
resultA := mload(0x40)
resultB := add(resultA, 0x40)
// Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words.
mstore(0x40, add(resultB, 0x40))
// Zeroize the length slots.
mstore(resultA, 0)
mstore(resultB, 0)
// Store the lengths and bytes.
mstore(add(resultA, 0x1f), packed)
mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA))))
// Right pad with zeroes.
mstore(add(add(resultA, 0x20), mload(resultA)), 0)
mstore(add(add(resultB, 0x20), mload(resultB)), 0)
}
}
/// @dev Directly returns `a` without copying.
function directReturn(string memory a) internal pure {
assembly {
// Assumes that the string does not start from the scratch space.
let retStart := sub(a, 0x20)
let retUnpaddedSize := add(mload(a), 0x40)
// Right pad with zeroes. Just in case the string is produced
// by a method that doesn't zero right pad.
mstore(add(retStart, retUnpaddedSize), 0)
// Store the return offset.
mstore(retStart, 0x20)
// End the transaction, returning the string.
return(retStart, and(not(0x1f), add(0x1f, retUnpaddedSize)))
}
}
}// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IFactory} from "../interfaces/factories/IFactory.sol";
import {IMarketConfigurator} from "../interfaces/IMarketConfigurator.sol";
import {IMarketConfiguratorFactory} from "../interfaces/IMarketConfiguratorFactory.sol";
import {Call} from "../interfaces/Types.sol";
import {AP_MARKET_CONFIGURATOR_FACTORY, NO_VERSION_CONTROL} from "../libraries/ContractLiterals.sol";
import {DeployerTrait} from "../traits/DeployerTrait.sol";
abstract contract AbstractFactory is DeployerTrait, IFactory {
address public immutable override marketConfiguratorFactory;
modifier onlyMarketConfigurators() {
_ensureCallerIsMarketConfigurator();
_;
}
constructor(address addressProvider_) DeployerTrait(addressProvider_) {
marketConfiguratorFactory = _getAddressOrRevert(AP_MARKET_CONFIGURATOR_FACTORY, NO_VERSION_CONTROL);
}
// ------------- //
// CONFIGURATION //
// ------------- //
function configure(address, bytes calldata callData) external virtual override returns (Call[] memory) {
revert ForbiddenConfigurationCallException(bytes4(callData));
}
function emergencyConfigure(address, bytes calldata callData) external virtual override returns (Call[] memory) {
revert ForbiddenEmergencyConfigurationCallException(bytes4(callData));
}
// --------- //
// INTERNALS //
// --------- //
function _ensureCallerIsMarketConfigurator() internal view {
if (!IMarketConfiguratorFactory(marketConfiguratorFactory).isMarketConfigurator(msg.sender)) {
revert CallerIsNotMarketConfiguratorException(msg.sender);
}
}
function _authorizeFactory(address marketConfigurator, address suite, address target)
internal
view
returns (Call memory)
{
return Call({
target: marketConfigurator,
callData: abi.encodeCall(IMarketConfigurator.authorizeFactory, (address(this), suite, target))
});
}
function _unauthorizeFactory(address marketConfigurator, address suite, address target)
internal
view
returns (Call memory)
{
return Call({
target: marketConfigurator,
callData: abi.encodeCall(IMarketConfigurator.unauthorizeFactory, (address(this), suite, target))
});
}
}// SPDX-License-Identifier: BUSL-1.1 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2025. pragma solidity ^0.8.23; uint256 constant NO_VERSION_CONTROL = 0; // Contract types and prefixes bytes32 constant AP_ACCOUNT_FACTORY_DEFAULT = "ACCOUNT_FACTORY::DEFAULT"; bytes32 constant AP_ACL = "ACL"; bytes32 constant AP_ADDRESS_PROVIDER = "ADDRESS_PROVIDER"; bytes32 constant AP_BOT_LIST = "BOT_LIST"; bytes32 constant AP_BYTECODE_REPOSITORY = "BYTECODE_REPOSITORY"; bytes32 constant AP_CONTRACTS_REGISTER = "CONTRACTS_REGISTER"; bytes32 constant AP_CREDIT_CONFIGURATOR = "CREDIT_CONFIGURATOR"; bytes32 constant AP_CREDIT_FACADE = "CREDIT_FACADE"; bytes32 constant AP_CREDIT_FACTORY = "CREDIT_FACTORY"; bytes32 constant AP_CREDIT_MANAGER = "CREDIT_MANAGER"; bytes32 constant AP_CROSS_CHAIN_GOVERNANCE = "CROSS_CHAIN_GOVERNANCE"; bytes32 constant AP_CROSS_CHAIN_GOVERNANCE_PROXY = "CROSS_CHAIN_GOVERNANCE_PROXY"; bytes32 constant AP_CROSS_CHAIN_MULTISIG = "CROSS_CHAIN_MULTISIG"; bytes32 constant AP_GEAR_STAKING = "GEAR_STAKING"; bytes32 constant AP_GEAR_TOKEN = "GLOBAL::GEAR_TOKEN"; bytes32 constant AP_GOVERNOR = "GOVERNOR"; bytes32 constant AP_INSTANCE_MANAGER = "INSTANCE_MANAGER"; bytes32 constant AP_INSTANCE_MANAGER_PROXY = "INSTANCE_MANAGER_PROXY"; bytes32 constant AP_INTEREST_RATE_MODEL_DEFAULT = "IRM::DEFAULT"; bytes32 constant AP_INTEREST_RATE_MODEL_FACTORY = "INTEREST_RATE_MODEL_FACTORY"; bytes32 constant AP_INTEREST_RATE_MODEL_LINEAR = "IRM::LINEAR"; bytes32 constant AP_LOSS_POLICY_ALIASED = "LOSS_POLICY::ALIASED"; bytes32 constant AP_LOSS_POLICY_DEFAULT = "LOSS_POLICY::DEFAULT"; bytes32 constant AP_LOSS_POLICY_FACTORY = "LOSS_POLICY_FACTORY"; bytes32 constant AP_MARKET_CONFIGURATOR = "MARKET_CONFIGURATOR"; bytes32 constant AP_MARKET_CONFIGURATOR_FACTORY = "MARKET_CONFIGURATOR_FACTORY"; bytes32 constant AP_MARKET_CONFIGURATOR_LEGACY = "MARKET_CONFIGURATOR::LEGACY"; bytes32 constant AP_POOL = "POOL"; bytes32 constant AP_POOL_FACTORY = "POOL_FACTORY"; bytes32 constant AP_POOL_QUOTA_KEEPER = "POOL_QUOTA_KEEPER"; bytes32 constant AP_PRICE_FEED_STORE = "PRICE_FEED_STORE"; bytes32 constant AP_PRICE_ORACLE = "PRICE_ORACLE"; bytes32 constant AP_PRICE_ORACLE_FACTORY = "PRICE_ORACLE_FACTORY"; bytes32 constant AP_RATE_KEEPER_FACTORY = "RATE_KEEPER_FACTORY"; bytes32 constant AP_RATE_KEEPER_GAUGE = "RATE_KEEPER::GAUGE"; bytes32 constant AP_RATE_KEEPER_TUMBLER = "RATE_KEEPER::TUMBLER"; bytes32 constant AP_TREASURY = "TREASURY"; bytes32 constant AP_TREASURY_PROXY = "TREASURY_PROXY"; bytes32 constant AP_TREASURY_SPLITTER = "TREASURY_SPLITTER"; bytes32 constant AP_WETH_TOKEN = "WETH_TOKEN"; bytes32 constant AP_ZERO_PRICE_FEED = "PRICE_FEED::ZERO"; // Common domains bytes32 constant DOMAIN_ACCOUNT_FACTORY = "ACCOUNT_FACTORY"; bytes32 constant DOMAIN_ADAPTER = "ADAPTER"; bytes32 constant DOMAIN_BOT = "BOT"; bytes32 constant DOMAIN_CREDIT_MANAGER = "CREDIT_MANAGER"; bytes32 constant DOMAIN_DEGEN_NFT = "DEGEN_NFT"; bytes32 constant DOMAIN_IRM = "IRM"; bytes32 constant DOMAIN_LOSS_POLICY = "LOSS_POLICY"; bytes32 constant DOMAIN_POOL = "POOL"; bytes32 constant DOMAIN_PRICE_FEED = "PRICE_FEED"; bytes32 constant DOMAIN_RATE_KEEPER = "RATE_KEEPER"; bytes32 constant DOMAIN_ZAPPER = "ZAPPER"; // Roles bytes32 constant ROLE_EMERGENCY_LIQUIDATOR = "EMERGENCY_LIQUIDATOR"; bytes32 constant ROLE_PAUSABLE_ADMIN = "PAUSABLE_ADMIN"; bytes32 constant ROLE_UNPAUSABLE_ADMIN = "UNPAUSABLE_ADMIN";
// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IAddressProvider as IAddressProviderBase} from
"@gearbox-protocol/core-v3/contracts/interfaces/base/IAddressProvider.sol";
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {IImmutableOwnableTrait} from "./base/IImmutableOwnableTrait.sol";
import {AddressProviderEntry} from "./Types.sol";
/// @title Address provider interface
interface IAddressProvider is IAddressProviderBase, IVersion, IImmutableOwnableTrait {
// ------ //
// EVENTS //
// ------ //
event SetAddress(bytes32 indexed key, uint256 indexed ver, address indexed value);
// ------ //
// ERRORS //
// ------ //
error AddressNotFoundException(bytes32 key, uint256 ver);
error InvalidVersionException(bytes32 key, uint256 ver);
error VersionNotFoundException(bytes32 key);
error ZeroAddressException(bytes32 key);
// ------- //
// GETTERS //
// ------- //
function getAddress(bytes32 key, uint256 ver) external view returns (address);
function getAddressOrRevert(bytes32 key, uint256 ver) external view override returns (address);
function getKeys() external view returns (bytes32[] memory);
function getVersions(bytes32 key) external view returns (uint256[] memory);
function getAllEntries() external view returns (AddressProviderEntry[] memory);
function getLatestVersion(bytes32 key) external view returns (uint256);
function getLatestMinorVersion(bytes32 key, uint256 majorVersion) external view returns (uint256);
function getLatestPatchVersion(bytes32 key, uint256 minorVersion) external view returns (uint256);
// ------------- //
// CONFIGURATION //
// ------------- //
function setAddress(bytes32 key, address value, bool saveVersion) external;
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IACLTrait} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IACLTrait.sol";
import {IContractsRegister as IContractsRegisterBase} from
"@gearbox-protocol/core-v3/contracts/interfaces/base/IContractsRegister.sol";
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
interface IContractsRegister is IContractsRegisterBase, IVersion, IACLTrait {
// ------ //
// EVENTS //
// ------ //
event RegisterMarket(address indexed pool, address indexed priceOracle, address indexed lossPolicy);
event ShutdownMarket(address indexed pool);
event RegisterCreditSuite(address indexed pool, address indexed creditManager);
event ShutdownCreditSuite(address indexed pool, address indexed creditManager);
event SetPriceOracle(address indexed pool, address indexed priceOracle);
event SetLossPolicy(address indexed pool, address indexed lossPolicy);
// ------ //
// ERRORS //
// ------ //
error MarketNotRegisteredException(address pool);
error MarketShutDownException(address pool);
error MarketNotEmptyException(address pool);
error CreditSuiteNotRegisteredException(address creditManager);
error CreditSuiteShutDownException(address creditManager);
// ------- //
// MARKETS //
// ------- //
function getShutdownPools() external view returns (address[] memory);
function getPriceOracle(address pool) external view returns (address);
function getLossPolicy(address pool) external view returns (address);
function registerMarket(address pool, address priceOracle, address lossPolicy) external;
function shutdownMarket(address pool) external;
function setPriceOracle(address pool, address priceOracle) external;
function setLossPolicy(address pool, address lossPolicy) external;
// ------------- //
// CREDIT SUITES //
// ------------- //
function getCreditManagers(address pool) external view returns (address[] memory);
function getShutdownCreditManagers() external view returns (address[] memory);
function getShutdownCreditManagers(address pool) external view returns (address[] memory);
function registerCreditSuite(address creditManager) external;
function shutdownCreditSuite(address creditManager) external;
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {IDeployerTrait} from "../base/IDeployerTrait.sol";
import {Call} from "../Types.sol";
interface IFactory is IVersion, IDeployerTrait {
// ------ //
// ERRORS //
// ------ //
error CallerIsNotMarketConfiguratorException(address caller);
error ForbiddenConfigurationCallException(bytes4 selector);
error ForbiddenEmergencyConfigurationCallException(bytes4 selector);
error InvalidConstructorParamsException();
// --------------- //
// STATE VARIABLES //
// --------------- //
function marketConfiguratorFactory() external view returns (address);
// ------------- //
// CONFIGURATION //
// ------------- //
function configure(address target, bytes calldata callData) external returns (Call[] memory calls);
function emergencyConfigure(address target, bytes calldata callData) external returns (Call[] memory calls);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {IImmutableOwnableTrait} from "./base/IImmutableOwnableTrait.sol";
import {AuditReport, Bytecode} from "./Types.sol";
/// @title Bytecode repository interface
interface IBytecodeRepository is IVersion, IImmutableOwnableTrait {
// ------ //
// EVENTS //
// ------ //
event AddAuditor(address indexed auditor, string name);
event AddPublicDomain(bytes32 indexed domain);
event AddSystemDomain(bytes32 indexed domain);
event AllowContract(bytes32 indexed bytecodeHash, bytes32 indexed contractType, uint256 indexed version);
event AuditBytecode(bytes32 indexed bytecodeHash, address indexed auditor, string reportUrl, bytes signature);
event DeployContract(
bytes32 indexed bytecodeHash,
bytes32 indexed contractType,
uint256 indexed version,
address contractAddress,
bytes constructorParams
);
event ForbidContract(bytes32 indexed bytecodeHash, bytes32 indexed contractType, uint256 indexed version);
event ForbidInitCode(bytes32 indexed initCodeHash);
event RemoveAuditor(address indexed auditor);
event RemoveContractTypeOwner(bytes32 indexed contractType);
event SetContractTypeOwner(bytes32 indexed contractType, address indexed owner);
event SetTokenSpecificPostfix(address indexed token, bytes32 indexed postfix);
event UploadBytecode(
bytes32 indexed bytecodeHash,
bytes32 indexed contractType,
uint256 indexed version,
address author,
string source,
bytes signature
);
// ------ //
// ERRORS //
// ------ //
error AuditorIsNotApprovedException(address auditor);
error AuthorIsNotContractTypeOwnerException(bytes32 contractType, address author);
error BytecodeIsAlreadyAllowedException(bytes32 contractType, uint256 version);
error BytecodeIsAlreadySignedByAuditorException(bytes32 bytecodeHash, address auditor);
error BytecodeIsNotAllowedException(bytes32 contractType, uint256 version);
error BytecodeIsNotAuditedException(bytes32 bytecodeHash);
error BytecodeIsNotUploadedException(bytes32 bytecodeHash);
error CallerIsNotBytecodeAuthorException(address caller);
error ContractIsAlreadyDeployedException(address deployedContract);
error ContractTypeIsNotInPublicDomainException(bytes32 contractType);
error DomainIsAlreadyMarkedAsPublicException(bytes32 domain);
error DomainIsAlreadyMarkedAsSystemException(bytes32 domain);
error InitCodeIsEmptyException();
error InitCodeIsForbiddenException(bytes32 initCodeHash);
error InvalidAuditorSignatureException(address auditor);
error InvalidAuthorSignatureException(address author);
error InvalidBytecodeException(bytes32 bytecodeHash);
error InvalidContractTypeException(bytes32 contractType);
error InvalidDomainException(bytes32 domain);
error InvalidPostfixException(bytes32 postfix);
error InvalidVersionException(bytes32 contractType, uint256 version);
error VersionNotFoundException(bytes32 contractType);
// --------------- //
// EIP-712 GETTERS //
// --------------- //
function BYTECODE_TYPEHASH() external view returns (bytes32);
function AUDIT_REPORT_TYPEHASH() external view returns (bytes32);
function domainSeparatorV4() external view returns (bytes32);
function computeBytecodeHash(Bytecode calldata bytecode) external view returns (bytes32);
function computeAuditReportHash(bytes32 bytecodeHash, AuditReport calldata report)
external
view
returns (bytes32);
// ------------------- //
// DEPLOYING CONTRACTS //
// ------------------- //
function isDeployedFromRepository(address deployedContract) external view returns (bool);
function getDeployedContractBytecodeHash(address deployedContract) external view returns (bytes32);
function computeAddress(
bytes32 contractType,
uint256 version,
bytes calldata constructorParams,
bytes32 salt,
address deployer
) external view returns (address);
function deploy(bytes32 contractType, uint256 version, bytes calldata constructorParams, bytes32 salt)
external
returns (address);
// ------------------ //
// UPLOADING BYTECODE //
// ------------------ //
function getBytecode(bytes32 bytecodeHash) external view returns (Bytecode memory);
function isBytecodeUploaded(bytes32 bytecodeHash) external view returns (bool);
function uploadBytecode(Bytecode calldata bytecode) external;
// ----------------- //
// AUDITING BYTECODE //
// ----------------- //
function isBytecodeAudited(bytes32 bytecodeHash) external view returns (bool);
function getAuditReports(bytes32 bytecodeHash) external view returns (AuditReport[] memory);
function getAuditReport(bytes32 bytecodeHash, uint256 index) external view returns (AuditReport memory);
function getNumAuditReports(bytes32 bytecodeHash) external view returns (uint256);
function submitAuditReport(bytes32 bytecodeHash, AuditReport calldata auditReport) external;
// ----------------- //
// ALLOWING BYTECODE //
// ----------------- //
function getAllowedBytecodeHash(bytes32 contractType, uint256 version) external view returns (bytes32);
function getContractTypeOwner(bytes32 contractType) external view returns (address);
function allowSystemContract(bytes32 bytecodeHash) external;
function allowPublicContract(bytes32 bytecodeHash) external;
function removePublicContractType(bytes32 contractType) external;
// ------------------ //
// DOMAINS MANAGEMENT //
// ------------------ //
function isSystemDomain(bytes32 domain) external view returns (bool);
function getSystemDomains() external view returns (bytes32[] memory);
function isPublicDomain(bytes32 domain) external view returns (bool);
function getPublicDomains() external view returns (bytes32[] memory);
function addPublicDomain(bytes32 domain) external;
// ------------------- //
// AUDITORS MANAGEMENT //
// ------------------- //
function isAuditor(address auditor) external view returns (bool);
function getAuditors() external view returns (address[] memory);
function getAuditorName(address auditor) external view returns (string memory);
function addAuditor(address auditor, string calldata name) external;
function removeAuditor(address auditor) external;
// -------------------- //
// FORBIDDING INIT CODE //
// -------------------- //
function isInitCodeForbidden(bytes32 initCodeHash) external view returns (bool);
function forbidInitCode(bytes32 initCodeHash) external;
// ------------------------ //
// TOKENS WITH CUSTOM LOGIC //
// ------------------------ //
function getTokenSpecificPostfix(address token) external view returns (bytes32);
function setTokenSpecificPostfix(address token, bytes32 postfix) external;
// --------------- //
// VERSION CONTROL //
// --------------- //
function getVersions(bytes32 contractType) external view returns (uint256[] memory);
function getLatestVersion(bytes32 contractType) external view returns (uint256);
function getLatestMinorVersion(bytes32 contractType, uint256 majorVersion) external view returns (uint256);
function getLatestPatchVersion(bytes32 contractType, uint256 minorVersion) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {IDeployerTrait} from "./base/IDeployerTrait.sol";
import {Call, DeployParams, MarketFactories} from "./Types.sol";
interface IMarketConfigurator is IVersion, IDeployerTrait {
// ------ //
// EVENTS //
// ------ //
event SetEmergencyAdmin(address indexed newEmergencyAdmin);
event GrantRole(bytes32 indexed role, address indexed account);
event RevokeRole(bytes32 indexed role, address indexed account);
event EmergencyRevokeRole(bytes32 indexed role, address indexed account);
event CreateMarket(
address indexed pool,
address priceOracle,
address interestRateModel,
address rateKeeper,
address lossPolicy,
MarketFactories factories
);
event ShutdownMarket(address indexed pool);
event AddToken(address indexed pool, address indexed token);
event ConfigurePool(address indexed pool, bytes data);
event EmergencyConfigurePool(address indexed pool, bytes data);
event CreateCreditSuite(address indexed creditManager, address factory);
event ShutdownCreditSuite(address indexed creditManager);
event ConfigureCreditSuite(address indexed creditManager, bytes data);
event EmergencyConfigureCreditSuite(address indexed creditManager, bytes data);
event UpdatePriceOracle(address indexed pool, address priceOracle);
event ConfigurePriceOracle(address indexed pool, bytes data);
event EmergencyConfigurePriceOracle(address indexed pool, bytes data);
event UpdateInterestRateModel(address indexed pool, address interestRateModel);
event ConfigureInterestRateModel(address indexed pool, bytes data);
event EmergencyConfigureInterestRateModel(address indexed pool, bytes data);
event UpdateRateKeeper(address indexed pool, address rateKeeper);
event ConfigureRateKeeper(address indexed pool, bytes data);
event EmergencyConfigureRateKeeper(address indexed pool, bytes data);
event UpdateLossPolicy(address indexed pool, address lossPolicy);
event ConfigureLossPolicy(address indexed pool, bytes data);
event EmergencyConfigureLossPolicy(address indexed pool, bytes data);
event AddPeripheryContract(bytes32 indexed domain, address indexed peripheryContract);
event RemovePeripheryContract(bytes32 indexed domain, address indexed peripheryContract);
event AuthorizeFactory(address indexed factory, address indexed suite, address indexed target);
event UnauthorizeFactory(address indexed factory, address indexed suite, address indexed target);
event UpgradePoolFactory(address indexed pool, address factory);
event UpgradePriceOracleFactory(address indexed pool, address factory);
event UpgradeInterestRateModelFactory(address indexed pool, address factory);
event UpgradeRateKeeperFactory(address indexed pool, address factory);
event UpgradeLossPolicyFactory(address indexed pool, address factory);
event UpgradeCreditFactory(address indexed creditManager, address factory);
event ExecuteHook(address indexed target, bytes callData);
// ------ //
// ERRORS //
// ------ //
error CallerIsNotAdminException(address caller);
error CallerIsNotEmergencyAdminException(address caller);
error CallerIsNotSelfException(address caller);
error CreditSuiteNotRegisteredException(address creditManager);
error IncorrectMinorVersionException(uint256 version);
error IncorrectPeripheryContractException(address peripheryContract);
error MarketNotRegisteredException(address pool);
error UnauthorizedFactoryException(address factory, address target);
// --------------- //
// STATE VARIABLES //
// --------------- //
function admin() external view returns (address);
function emergencyAdmin() external view returns (address);
function curatorName() external view returns (string memory);
function acl() external view returns (address);
function contractsRegister() external view returns (address);
function treasury() external view returns (address);
// ---------------- //
// ROLES MANAGEMENT //
// ---------------- //
function setEmergencyAdmin(address newEmergencyAdmin) external;
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function emergencyRevokeRole(bytes32 role, address account) external;
// ----------------- //
// MARKET MANAGEMENT //
// ----------------- //
function previewCreateMarket(uint256 minorVersion, address underlying, string calldata name, string calldata symbol)
external
view
returns (address pool);
function createMarket(
uint256 minorVersion,
address underlying,
string calldata name,
string calldata symbol,
DeployParams calldata interestRateModelParams,
DeployParams calldata rateKeeperParams,
DeployParams calldata lossPolicyParams,
address underlyingPriceFeed
) external returns (address pool);
function shutdownMarket(address pool) external;
function addToken(address pool, address token, address priceFeed) external;
function configurePool(address pool, bytes calldata data) external;
function emergencyConfigurePool(address pool, bytes calldata data) external;
// ----------------------- //
// CREDIT SUITE MANAGEMENT //
// ----------------------- //
function previewCreateCreditSuite(uint256 minorVersion, address pool, bytes calldata encodedParams)
external
view
returns (address creditManager);
function previewCreateCreditSuite(
uint256 marketMinorVersion,
uint256 creditSuiteMinorVersion,
address underlying,
string calldata name,
string calldata symbol,
bytes calldata encodedParams
) external view returns (address creditManager);
function createCreditSuite(uint256 minorVersion, address pool, bytes calldata encdodedParams)
external
returns (address creditManager);
function shutdownCreditSuite(address creditManager) external;
function configureCreditSuite(address creditManager, bytes calldata data) external;
function emergencyConfigureCreditSuite(address creditManager, bytes calldata data) external;
// ----------------------- //
// PRICE ORACLE MANAGEMENT //
// ----------------------- //
function updatePriceOracle(address pool) external returns (address priceOracle);
function configurePriceOracle(address pool, bytes calldata data) external;
function emergencyConfigurePriceOracle(address pool, bytes calldata data) external;
// -------------- //
// IRM MANAGEMENT //
// -------------- //
function updateInterestRateModel(address pool, DeployParams calldata params) external returns (address irm);
function configureInterestRateModel(address pool, bytes calldata data) external;
function emergencyConfigureInterestRateModel(address pool, bytes calldata data) external;
// ---------------------- //
// RATE KEEPER MANAGEMENT //
// ---------------------- //
function updateRateKeeper(address pool, DeployParams calldata params) external returns (address rateKeeper);
function configureRateKeeper(address pool, bytes calldata data) external;
function emergencyConfigureRateKeeper(address pool, bytes calldata data) external;
// -–-------------------- //
// LOSS POLICY MANAGEMENT //
// -–-------------------- //
function updateLossPolicy(address pool, DeployParams calldata params) external returns (address lossPolicy);
function configureLossPolicy(address pool, bytes calldata data) external;
function emergencyConfigureLossPolicy(address pool, bytes calldata data) external;
// --------- //
// PERIPHERY //
// --------- //
function getPeripheryContracts(bytes32 domain) external view returns (address[] memory);
function isPeripheryContract(bytes32 domain, address peripheryContract) external view returns (bool);
function addPeripheryContract(address peripheryContract) external;
function removePeripheryContract(address peripheryContract) external;
// --------- //
// FACTORIES //
// --------- //
function getMarketFactories(address pool) external view returns (MarketFactories memory);
function getCreditFactory(address creditManager) external view returns (address);
function getAuthorizedFactory(address target) external view returns (address);
function getFactoryTargets(address factory, address suite) external view returns (address[] memory);
function authorizeFactory(address factory, address suite, address target) external;
function unauthorizeFactory(address factory, address suite, address target) external;
function upgradePoolFactory(address pool) external;
function upgradePriceOracleFactory(address pool) external;
function upgradeInterestRateModelFactory(address pool) external;
function upgradeRateKeeperFactory(address pool) external;
function upgradeLossPolicyFactory(address pool) external;
function upgradeCreditFactory(address creditManager) external;
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
/// @title Deployer trait interface
interface IDeployerTrait {
function addressProvider() external view returns (address);
function bytecodeRepository() external view returns (address);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {Call, DeployResult} from "../Types.sol";
import {IFactory} from "./IFactory.sol";
interface ICreditFactory is IFactory {
function deployCreditSuite(address pool, bytes calldata encodedParams) external returns (DeployResult memory);
function computeCreditManagerAddress(
address marketConfigurator,
address pool,
address underlying,
address priceOracle,
bytes calldata encodedParams
) external view returns (address);
// ------------ //
// CREDIT HOOKS //
// ------------ //
function onUpdatePriceOracle(address creditManager, address newPriceOracle, address oldPriceOracle)
external
returns (Call[] memory calls);
function onUpdateLossPolicy(address creditManager, address newLossPolicy, address oldLossPolicy)
external
returns (Call[] memory calls);
}// 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
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {IVersion} from "@gearbox-protocol/core-v3/contracts/interfaces/base/IVersion.sol";
import {IDeployerTrait} from "./base/IDeployerTrait.sol";
/// @title Market configurator factory interface
interface IMarketConfiguratorFactory is IVersion, IDeployerTrait {
// ------ //
// EVENTS //
// ------ //
event CreateMarketConfigurator(address indexed marketConfigurator, string name);
event ShutdownMarketConfigurator(address indexed marketConfigurator);
// ------ //
// ERRORS //
// ------ //
error CallerIsNotCrossChainGovernanceException(address caller);
error CallerIsNotMarketConfiguratorAdminException(address caller);
error CantShutdownMarketConfiguratorException(address marketConfigurator);
error MarketConfiguratorIsAlreadyAddedException(address marketConfigurator);
error MarketConfiguratorIsAlreadyShutdownException(address marketConfigruator);
error MarketConfiguratorIsNotRegisteredException(address marketConfigurator);
// ------- //
// GETTERS //
// ------- //
function isMarketConfigurator(address account) external view returns (bool);
function getMarketConfigurators() external view returns (address[] memory);
function getMarketConfigurator(uint256 index) external view returns (address);
function getNumMarketConfigurators() external view returns (uint256);
function getShutdownMarketConfigurators() external view returns (address[] memory);
// ------------- //
// CONFIGURATION //
// ------------- //
function createMarketConfigurator(
address emergencyAdmin,
address adminFeeTreasury,
string calldata curatorName,
bool deployGovernor
) external returns (address marketConfigurator);
function shutdownMarketConfigurator(address marketConfigurator) external;
function addMarketConfigurator(address marketConfigurator) 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.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
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
/// @title Immutable ownable trait interface
/// @notice Interface for contracts with immutable owner functionality
interface IImmutableOwnableTrait {
error CallerIsNotOwnerException(address caller);
/// @notice Returns the immutable owner address
function owner() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH is IERC20 {
event Deposit(address indexed dst, uint wad);
event Withdrawal(address indexed src, uint wad);
function deposit() external payable;
function withdraw(uint256 amount) external;
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
import {DeployParams} from "../Types.sol";
struct CreditManagerParams {
uint8 maxEnabledTokens;
uint16 feeInterest;
uint16 feeLiquidation;
uint16 liquidationPremium;
uint16 feeLiquidationExpired;
uint16 liquidationPremiumExpired;
uint128 minDebt;
uint128 maxDebt;
string name;
DeployParams accountFactoryParams;
}
struct CreditFacadeParams {
address degenNFT;
bool expirable;
bool migrateBotList;
}
interface ICreditConfigureActions {
function upgradeCreditConfigurator() external;
function upgradeCreditFacade(CreditFacadeParams calldata params) external;
function allowAdapter(DeployParams calldata params) external;
function forbidAdapter(address adapter) external;
function configureAdapterFor(address targetContract, bytes calldata data) external;
function setFees(
uint16 feeLiquidation,
uint16 liquidationPremium,
uint16 feeLiquidationExpired,
uint16 liquidationPremiumExpired
) external;
function setMaxDebtPerBlockMultiplier(uint8 newMaxDebtLimitPerBlockMultiplier) external;
function addCollateralToken(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 setExpirationDate(uint40 newExpirationDate) external;
function pause() external;
function unpause() 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";
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.
* @notice Compared to the standard ERC20, this implementation offers several enhancements:
* 1. more gas-efficient, providing significant savings in transaction costs.
* 2. support for different permit implementations
* 3. forceApprove functionality
* 4. support for WETH deposit and withdraw
*/
library SafeERC20 {
error SafeTransferFailed();
error SafeTransferFromFailed();
error ForceApproveFailed();
error SafeIncreaseAllowanceFailed();
error SafeDecreaseAllowanceFailed();
error SafePermitBadLength();
error Permit2TransferAmountTooHigh();
// Uniswap Permit2 address
address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857; // SafePermitBadLength.selector
uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
/**
* @notice Fetches the balance of a specific ERC20 token held by an account.
* Consumes less gas then regular `ERC20.balanceOf`.
* @param token The IERC20 token contract for which the balance will be fetched.
* @param account The address of the account whose token balance will be fetched.
* @return tokenBalance The balance of the specified ERC20 token held by the account.
*/
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())
}
}
}
/**
* @notice Attempts to safely transfer tokens from one address to another.
* @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom.
* Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param from The address from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param amount The amount of tokens to transfer.
* @param permit2 If true, uses the Permit2 standard for the transfer; otherwise uses the standard ERC20 transferFrom.
*/
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);
}
}
/**
* @notice Attempts to safely transfer tokens from one address to another using the ERC20 standard.
* @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param from The address from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param amount The amount of tokens to transfer.
*/
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();
}
/**
* @notice Attempts to safely transfer tokens from one address to another using the Permit2 standard.
* @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param from The address from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param amount The amount of tokens to transfer.
*/
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();
}
/**
* @notice Attempts to safely transfer tokens to another address.
* @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data.
* @param token The IERC20 token contract from which the tokens will be transferred.
* @param to The address to which the tokens will be transferred.
* @param value The amount of tokens to transfer.
*/
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
if (!_makeCall(token, token.transfer.selector, to, value)) {
revert SafeTransferFailed();
}
}
/**
* @notice Attempts to approve a spender to spend a certain amount of tokens.
* @dev If `approve(from, to, amount)` fails, it tries to set the allowance to zero, and retries the `approve` call.
* @param token The IERC20 token contract on which the call will be made.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
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();
}
}
}
/**
* @notice Safely increases the allowance of a spender.
* @dev Increases with safe math check. Checks if the increased allowance will overflow, if yes, then it reverts the transaction.
* Then uses `forceApprove` to increase the allowance.
* @param token The IERC20 token contract on which the call will be made.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to increase the allowance by.
*/
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);
}
/**
* @notice Safely decreases the allowance of a spender.
* @dev Decreases with safe math check. Checks if the decreased allowance will underflow, if yes, then it reverts the transaction.
* Then uses `forceApprove` to increase the allowance.
* @param token The IERC20 token contract on which the call will be made.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to decrease the allowance by.
*/
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);
}
/**
* @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters.
* Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).
* @dev Wraps `tryPermit` function and forwards revert reason if permit fails.
* @param token The IERC20 token to execute the permit function on.
* @param permit The permit data to be used in the function call.
*/
function safePermit(IERC20 token, bytes calldata permit) internal {
if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert();
}
/**
* @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters.
* Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2).
* @dev Wraps `tryPermit` function and forwards revert reason if permit fails.
* @param token The IERC20 token to execute the permit function on.
* @param owner The owner of the tokens for which the permit is made.
* @param spender The spender allowed to spend the tokens by the permit.
* @param permit The permit data to be used in the function call.
*/
function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal {
if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert();
}
/**
* @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters.
* @dev Invokes `tryPermit` with sender as owner and contract as spender.
* @param token The IERC20 token to execute the permit function on.
* @param permit The permit data to be used in the function call.
* @return success Returns true if the permit function was successfully executed, false otherwise.
*/
function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) {
return tryPermit(token, msg.sender, address(this), permit);
}
/**
* @notice The function attempts to call the permit function on a given ERC20 token.
* @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, and IPermit2.
* It accommodates both Compact and Full formats of these permit types.
* Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter
* for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by
* gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and
* zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one
* before invocation for optimized performance.
* @param token The address of the ERC20 token on which to call the permit function.
* @param owner The owner of the tokens. This address should have signed the off-chain permit.
* @param spender The address which will be approved for transfer of tokens.
* @param permit The off-chain permit data, containing different fields depending on the type of permit function.
* @return success A boolean indicating whether the permit call was successful.
*/
function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) {
// load function selectors for different permit standards
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 case for different permit lengths, indicating different permit standards
switch permit.length
// Compact IERC20Permit
case 100 {
mstore(ptr, permitSelector) // store selector
mstore(add(ptr, 0x04), owner) // store owner
mstore(add(ptr, 0x24), spender) // store spender
// Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs)
{ // stack too deep
let deadline := shr(224, calldataload(add(permit.offset, 0x20))) // loads permit.offset 0x20..0x23
let vs := calldataload(add(permit.offset, 0x44)) // loads permit.offset 0x44..0x63
calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // store value = copy permit.offset 0x00..0x19
mstore(add(ptr, 0x64), sub(deadline, 1)) // store deadline = deadline - 1
mstore(add(ptr, 0x84), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28)
calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // store r = copy permit.offset 0x24..0x43
mstore(add(ptr, 0xc4), shr(1, shl(1, vs))) // store s = vs without most significant bit
}
// 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)
}
// Compact IDaiLikePermit
case 72 {
mstore(ptr, daiPermitSelector) // store selector
mstore(add(ptr, 0x04), owner) // store owner
mstore(add(ptr, 0x24), spender) // store spender
// Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs)
{ // stack too deep
let expiry := shr(224, calldataload(add(permit.offset, 0x04))) // loads permit.offset 0x04..0x07
let vs := calldataload(add(permit.offset, 0x28)) // loads permit.offset 0x28..0x47
mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) // store nonce = copy permit.offset 0x00..0x03
mstore(add(ptr, 0x64), sub(expiry, 1)) // store expiry = expiry - 1
mstore(add(ptr, 0x84), true) // store allowed = true
mstore(add(ptr, 0xa4), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28)
calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // store r = copy permit.offset 0x08..0x27
mstore(add(ptr, 0xe4), shr(1, shl(1, vs))) // store s = vs without most significant bit
}
// 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)
}
// IERC20Permit
case 224 {
mstore(ptr, permitSelector)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// 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)
}
// IDaiLikePermit
case 256 {
mstore(ptr, daiPermitSelector)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// 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)
}
// Compact IPermit2
case 96 {
// Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs)
mstore(ptr, permit2Selector) // store selector
mstore(add(ptr, 0x04), owner) // store owner
mstore(add(ptr, 0x24), token) // store token
calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // store amount = copy permit.offset 0x00..0x13
// and(0xffffffffffff, ...) - conversion to uint48
mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff)
mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b
mstore(add(ptr, 0xa4), spender) // store spender
// and(0xffffffffffff, ...) - conversion to uint48
mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // store sigDeadline = ((permit.offset 0x1c..0x1f - 1) & 0xffffffffffff)
mstore(add(ptr, 0xe4), 0x100) // store offset = 256
mstore(add(ptr, 0x104), 0x40) // store length = 64
calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // store r = copy permit.offset 0x20..0x3f
calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // store vs = copy permit.offset 0x40..0x5f
// IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)
}
// IPermit2
case 352 {
mstore(ptr, permit2Selector)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)
}
// Unknown
default {
mstore(ptr, _PERMIT_LENGTH_ERROR)
revert(ptr, 4)
}
}
}
/**
* @dev Executes a low level call to a token contract, making it resistant to reversion and erroneous boolean returns.
* @param token The IERC20 token contract on which the call will be made.
* @param selector The function signature that is to be called on the token contract.
* @param to The address to which the token amount will be transferred.
* @param amount The token amount to be transferred.
* @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure.
* In case of success but no returned data, validates that the contract code exists.
* In case of returned data, ensures that it's a boolean `true`.
*/
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))
}
}
}
}
/**
* @notice Safely deposits a specified amount of Ether into the IWETH contract. Consumes less gas then regular `IWETH.deposit`.
* @param weth The IWETH token contract.
* @param amount The amount of Ether to deposit into the IWETH contract.
*/
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())
}
}
}
}
/**
* @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract. Consumes less gas then regular `IWETH.withdraw`.
* @dev Uses inline assembly to interact with the IWETH contract.
* @param weth The IWETH token contract.
* @param amount The amount of wrapped Ether to withdraw from the IWETH contract.
*/
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())
}
}
}
/**
* @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract to a specified recipient.
* Consumes less gas then regular `IWETH.withdraw`.
* @param weth The IWETH token contract.
* @param amount The amount of wrapped Ether to withdraw from the IWETH contract.
* @param to The recipient of the withdrawn Ether.
*/
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, 2024.
pragma solidity ^0.8.17;
import {IncorrectParameterException} from "../interfaces/IExceptions.sol";
/// @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 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 Returns a mask with only the least significant bit of `mask` enabled
/// @dev This function can be used to efficiently iterate over enabled bits in a mask
function lsbMask(uint256 mask) internal pure returns (uint256) {
unchecked {
return mask & uint256(-int256(mask)); // U:[BM-6]
}
}
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
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 {IACLTrait} from "./base/IACLTrait.sol";
import {IContractsRegisterTrait} from "./base/IContractsRegisterTrait.sol";
import {IVersion} from "./base/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, IACLTrait, IContractsRegisterTrait, IPoolV3Events, IERC4626, IERC20Permit {
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;
function pause() external;
function unpause() external;
}// 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 // Gearbox Protocol. Generalized leverage for DeFi protocols // (c) Gearbox Foundation, 2024. 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 attempting to connect a gauge to an incompatible pool quota keeper error IncompatibleGaugeException(); /// @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(); /// @notice Thrown if new credit configurator's set of allowed adapters differs from the current one error IncorrectAdaptersSetException(); /// @notice Thrown if attempting to schedule a token's LT ramping that is too short in duration error RampDurationTooShortException(); /// @notice Thrown if attempting to set liquidation fees such that the sum of premium and fee changes error InconsistentLiquidationFeesException(); /// @notice Thrown if attempting to set expired liquidation fees such that the sum of premium and fee changes error InconsistentExpiredLiquidationFeesException(); // ------------- // // 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(bytes4 selector); /// @notice Thrown if a liquidator tries to liquidate an account with a health factor above 1 error CreditAccountNotLiquidatableException(); /// @notice Thrown if a liquidator tries to liquidate an account with loss but violates the loss policy error CreditAccountNotLiquidatableWithLossException(); /// @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(address token); /// @notice Thrown when trying to perform an action that is forbidden when credit account has enabled forbidden tokens error ForbiddenTokensException(uint256 forbiddenTokensMask); /// @notice Thrown when forbidden token quota is increased during the multicall error ForbiddenTokenQuotaIncreasedException(address token); /// @notice Thrown when enabled forbidden token balance is increased during the multicall error ForbiddenTokenBalanceIncreasedException(address token); /// @notice Thrown when the remaining token balance is increased during the liquidation error RemainingTokenBalanceIncreasedException(address token); /// @notice Thrown if `botMulticall` is called by an address that is not approved by account owner or is forbidden error NotApprovedBotException(address bot); /// @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(uint256 permissions); /// @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(uint256 mask); /// @notice Thrown when trying to seize underlying token during partial liquidation error UnderlyingIsNotLiquidatableException(); /// @notice Thrown when amount of collateral seized during partial liquidation is less than required error SeizedLessThanRequiredException(uint256 seizedAmount); // ------ // // 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 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(); // -------- // // BOT LIST // // -------- // /// @notice Thrown when attempting to set non-zero permissions for a forbidden bot error InvalidBotException(); /// @notice Thrown when attempting to set permissions for a bot that don't meet its requirements error IncorrectBotPermissionsException(); /// @notice Thrown when attempting to set non-zero permissions for too many bots error TooManyActiveBotsException(); // --------------- // // 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 trying to apply an on-demand price update to a non-updatable price feed error PriceFeedIsNotUpdatableException(); /// @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: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2025.
pragma solidity ^0.8.23;
interface ICreditEmergencyConfigureActions {
function forbidAdapter(address adapter) external;
function forbidToken(address token) external;
function forbidBorrowing() external;
function pause() external;
}// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
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";
struct Balance {
address token;
uint256 balance;
}
struct BalanceWithMask {
address token;
uint256 tokenMask;
uint256 balance;
}
struct BalanceDelta {
address token;
int256 amount;
}
enum Comparison {
GREATER_OR_EQUAL,
LESS_OR_EQUAL
}
/// @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_OR_EQUAL && current >= value)
|| (comparison == Comparison.LESS_OR_EQUAL && 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 failedToken The first token for which the condition specified by `comparison` fails, if any
function compareBalances(address creditAccount, Balance[] memory balances, Comparison comparison)
internal
view
returns (address failedToken)
{
unchecked {
uint256 len = balances.length;
for (uint256 i; i < len; ++i) {
if (!BalancesLogic.checkBalance(creditAccount, balances[i].token, balances[i].balance, comparison)) {
return balances[i].token; // 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.lsbMask();
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 failedToken The first token for which the condition specified by `comparison` fails, if any
/// @dev This function assumes that `tokensMask` encodes a subset of tokens from `balances`
function compareBalances(
address creditAccount,
uint256 tokensMask,
BalanceWithMask[] memory balances,
Comparison comparison
) internal view returns (address failedToken) {
if (tokensMask == 0) return address(0);
unchecked {
uint256 len = balances.length;
for (uint256 i; i < len; ++i) {
if (tokensMask & balances[i].tokenMask == 0) continue;
if (!BalancesLogic.checkBalance(creditAccount, balances[i].token, balances[i].balance, comparison)) {
return balances[i].token; // U:[BLL-5]
}
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
import {IVersion} from "./IVersion.sol";
import {IStateSerializer} from "./IStateSerializer.sol";
/// @title Adapter interface
/// @notice Generic interface for an adapter that can be used to interact with external protocols.
/// Adapters can be assumed to be non-malicious since they are developed by Gearbox DAO.
/// @dev Adapters must have type `ADAPTER::{POSTFIX}`
interface IAdapter is IVersion, IStateSerializer {
/// @notice Credit manager this adapter is connected to
/// @dev Assumed to be an immutable state variable
function creditManager() external view returns (address);
/// @notice Target contract adapter helps to interact with
/// @dev Assumed to be an immutable state variable
function targetContract() external view returns (address);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
/// @title Version interface
/// @notice Defines contract version and type
interface IVersion {
/// @notice Contract version
function version() external view returns (uint256);
/// @notice Contract type
function contractType() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
interface IACLTrait {
function acl() external view returns (address);
}// 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
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
import {AllowanceAction} from "./ICreditConfiguratorV3.sol";
import "./ICreditFacadeV3Multicall.sol";
import {IACLTrait} from "./base/IACLTrait.sol";
import {PriceUpdate} from "./base/IPriceFeedStore.sol";
import {IVersion} from "./base/IVersion.sol";
/// @notice Multicall element
/// @param target Call target, which is either credit facade or adapter
/// @param callData Call data
struct MultiCall {
address target;
bytes callData;
}
/// @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 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
struct FullCheckParams {
uint256[] collateralHints;
uint16 minHealthFactor;
}
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 is partially liquidated
event PartiallyLiquidateCreditAccount(
address indexed creditAccount,
address indexed token,
address indexed liquidator,
uint256 repaidDebt,
uint256 seizedCollateral,
uint256 fee
);
/// @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 phantom token is withdrawn by account
event WithdrawPhantomToken(address indexed creditAccount, address indexed token, uint256 amount);
/// @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, IACLTrait, ICreditFacadeV3Events {
function creditManager() external view returns (address);
function underlying() external view returns (address);
function treasury() external view returns (address);
function priceFeedStore() 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 lossPolicy() external view returns (address);
function forbiddenTokenMask() external view returns (uint256);
// ------------------ //
// 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,
bytes memory lossPolicyData
) external;
function liquidateCreditAccount(address creditAccount, address to, MultiCall[] calldata calls) external;
function partiallyLiquidateCreditAccount(
address creditAccount,
address token,
uint256 repaidAmount,
uint256 minSeizedAmount,
address to,
PriceUpdate[] calldata priceUpdates
) external returns (uint256 seizedAmount);
function multicall(address creditAccount, MultiCall[] calldata calls) external payable;
function botMulticall(address creditAccount, MultiCall[] calldata calls) external;
// ------------- //
// CONFIGURATION //
// ------------- //
function setExpirationDate(uint40 newExpirationDate) external;
function setDebtLimits(uint128 newMinDebt, uint128 newMaxDebt, uint8 newMaxDebtPerBlockMultiplier) external;
function setLossPolicy(address newLossPolicy) external;
function setTokenAllowance(address token, AllowanceAction allowance) external;
function pause() external;
function unpause() 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())
}
}
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
import {IVersion} from "./base/IVersion.sol";
/// @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 variables (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;
}
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 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, uint256);
function addCollateral(address payer, address creditAccount, address token, uint256 amount)
external
returns (uint256);
function withdrawCollateral(address creditAccount, address token, uint256 amount, address to)
external
returns (uint256);
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;
// -------- //
// 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);
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 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 // 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
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
import {IVersion} from "./IVersion.sol";
import {IStateSerializer} from "./IStateSerializer.sol";
/// @title Account factory interface
/// @notice Generic interface for an account factory that can be used by credit managers to create credit accounts
/// @dev Account factories must have type `ACCOUNT_FACTORY::{POSTFIX}`
interface IAccountFactory is IVersion, IStateSerializer {
/// @notice Takes `creditAccount` from the account factory
/// @dev Parameters are kept for backward compatibility
function takeCreditAccount(uint256, uint256) external returns (address creditAccount);
/// @notice Returns `creditAccount` to the account factory
function returnCreditAccount(address creditAccount) external;
/// @notice Connects `creditManager` to the account factory, allowing it to take and return credit accounts
function addCreditManager(address creditManager) external;
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
import {IVersion} from "./IVersion.sol";
struct PriceUpdate {
address priceFeed;
bytes data;
}
interface IPriceFeedStore {
function getStalenessPeriod(address priceFeed) external view returns (uint32);
function updatePrices(PriceUpdate[] calldata updates) external;
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
import {IACLTrait} from "./base/IACLTrait.sol";
import {IVersion} from "./base/IVersion.sol";
enum AllowanceAction {
FORBID,
ALLOW
}
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);
// -------- //
// 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 new fee parameters are set in the credit manager
event UpdateFees(
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 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 new loss policy is set
event SetLossPolicy(address indexed lossPolicy);
/// @notice Emitted when a new expiration timestamp is set in the credit facade
event SetExpirationDate(uint40 expirationDate);
}
/// @title Credit configurator V3 interface
interface ICreditConfiguratorV3 is IVersion, IACLTrait, ICreditConfiguratorV3Events {
function creditManager() external view returns (address);
function creditFacade() external view returns (address);
function underlying() external view returns (address);
// ------ //
// TOKENS //
// ------ //
function makeAllTokensQuoted() external;
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;
// -------- //
// ADAPTERS //
// -------- //
function allowedAdapters() external view returns (address[] memory);
function allowAdapter(address adapter) external;
function forbidAdapter(address adapter) external;
// -------------- //
// CREDIT MANAGER //
// -------------- //
function setFees(
uint16 feeLiquidation,
uint16 liquidationPremium,
uint16 feeLiquidationExpired,
uint16 liquidationPremiumExpired
) external;
// -------- //
// UPGRADES //
// -------- //
function setPriceOracle(address newPriceOracle) external;
function setCreditFacade(address newCreditFacade, bool migrateParams) external;
function upgradeCreditConfigurator(address newCreditConfigurator) external;
// ------------- //
// CREDIT FACADE //
// ------------- //
function setDebtLimits(uint128 newMinDebt, uint128 newMaxDebt) external;
function setMaxDebtPerBlockMultiplier(uint8 newMaxDebtLimitPerBlockMultiplier) external;
function forbidBorrowing() external;
function setLossPolicy(address newLossPolicy) external;
function setExpirationDate(uint40 newExpirationDate) external;
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
interface IAddressProvider {
function getAddressOrRevert(bytes32 key, uint256 version) external view returns (address);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
/// @title State serializer interface
/// @notice Generic interface for a contract that can serialize its state into a bytes array
interface IStateSerializer {
/// @notice Serializes the state of the contract into a bytes array `serializedData`
function serialize() external view returns (bytes memory serializedData);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
interface IContractsRegister {
function isPool(address) external view returns (bool);
function getPools() external view returns (address[] memory);
function isCreditManager(address) external view returns (bool);
function getCreditManagers() external view returns (address[] memory);
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
import {BalanceDelta} from "../libraries/BalancesLogic.sol";
import {PriceUpdate} from "./base/IPriceFeedStore.sol";
// ----------- //
// PERMISSIONS //
// ----------- //
// NOTE: permissions 1 << 3, 1 << 4 and 1 << 7 were used by now deprecated methods, thus non-consecutive values
uint192 constant ADD_COLLATERAL_PERMISSION = 1 << 0;
uint192 constant INCREASE_DEBT_PERMISSION = 1 << 1;
uint192 constant DECREASE_DEBT_PERMISSION = 1 << 2;
uint192 constant WITHDRAW_COLLATERAL_PERMISSION = 1 << 5;
uint192 constant UPDATE_QUOTA_PERMISSION = 1 << 6;
uint192 constant SET_BOT_PERMISSIONS_PERMISSION = 1 << 8;
uint192 constant EXTERNAL_CALLS_PERMISSION = 1 << 16;
uint192 constant ALL_PERMISSIONS = ADD_COLLATERAL_PERMISSION | WITHDRAW_COLLATERAL_PERMISSION | UPDATE_QUOTA_PERMISSION
| INCREASE_DEBT_PERMISSION | DECREASE_DEBT_PERMISSION | SET_BOT_PERMISSIONS_PERMISSION | EXTERNAL_CALLS_PERMISSION;
uint192 constant OPEN_CREDIT_ACCOUNT_PERMISSIONS = ALL_PERMISSIONS & ~DECREASE_DEBT_PERMISSION;
uint192 constant CLOSE_CREDIT_ACCOUNT_PERMISSIONS = ALL_PERMISSIONS & ~INCREASE_DEBT_PERMISSION;
uint192 constant LIQUIDATE_CREDIT_ACCOUNT_PERMISSIONS =
EXTERNAL_CALLS_PERMISSION | ADD_COLLATERAL_PERMISSION | WITHDRAW_COLLATERAL_PERMISSION;
// ----- //
// FLAGS //
// ----- //
/// @dev Indicates that collateral check after the multicall can be skipped, set to true on account closure or liquidation
uint256 constant SKIP_COLLATERAL_CHECK_FLAG = 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_FLAG = 1 << 193;
/// @dev Indicates that the price updates call should be skipped, set to true on liquidation when the first call
/// of the multicall is `onDemandPriceUpdates`
uint256 constant SKIP_PRICE_UPDATES_CALL_FLAG = 1 << 194;
/// @dev Indicates that collateral check must revert if any forbidden token is encountered on the account,
/// set to true after risky operations, such as `increaseDebt` or `withdrawCollateral`
uint256 constant REVERT_ON_FORBIDDEN_TOKENS_FLAG = 1 << 195;
/// @dev Indicates that collateral check must be performed using safe prices, set to true on `withdrawCollateral`
/// or if account has enabled forbidden tokens
uint256 constant USE_SAFE_PRICES_FLAG = 1 << 196;
/// @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 Applies on-demand price feed updates
/// @param updates Array of price updates, see `PriceUpdate` for details
/// @dev Reverts if placed not at the first position in the multicall
/// @dev This method is available in all kinds of multicalls
function onDemandPriceUpdates(PriceUpdate[] calldata updates) 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.
/// Only the underlying token counts towards account's collateral value by default, while all other tokens
/// must be enabled as collateral by "purchasing" quota for it. Holding non-enabled token on account with
/// non-zero debt poses a risk of losing it entirely to the liquidator. Adding non-enabled tokens is still
/// supported to allow users to later swap them into enabled ones in the same multicall.
/// @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.
/// Only the underlying token counts towards account's collateral value by default, while all other tokens
/// must be enabled as collateral by "purchasing" quota for it. Holding non-enabled token on account with
/// non-zero debt poses a risk of losing it entirely to the liquidator. Adding non-enabled tokens is still
/// supported to allow users to later swap them into enabled ones in the same multicall.
/// @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 limits
/// @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 above allowed minimum or zero (maximum is not checked here
/// to allow small repayments and partial liquidations in case configurator lowers it)
/// @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 Collateral token to update the quota for (can't be underlying)
/// @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 for forbidden tokens
/// @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
/// @dev If `token` is a phantom token, it's withdrawn first, and its `depositedToken` is then sent to the recipient.
/// No slippage prevention mechanism is provided as withdrawals are assumed to happen at non-manipulatable rate.
/// Although an adapter call is made in process, permission for external calls is not required.
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. Underlying token is always
/// checked last so it's forbidden to pass its mask.
/// @param minHealthFactor Min account's health factor in bps in order not to revert, must be at least 10000
/// @dev This method can't be called during closure or liquidation
function setFullCheckParams(uint256[] calldata collateralHints, uint16 minHealthFactor) external;
/// @notice Sets `bot`'s permissions to manage account to `permissions`
/// @param bot Bot to set permissions for
/// @param permissions A bitmask encoding bot permissions
/// @dev Reverts if `permissions` has unexpected bits enabled or doesn't match permissions required by `bot`
function setBotPermissions(address bot, uint192 permissions) external;
}// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;
interface IContractsRegisterTrait {
function contractsRegister() external view returns (address);
}{
"remappings": [
"@1inch/=lib/@1inch/",
"@gearbox-protocol/=lib/@gearbox-protocol/",
"@openzeppelin/=lib/@openzeppelin/",
"@redstone-finance/=node_modules/@redstone-finance/",
"@solady/=lib/@solady/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/@openzeppelin/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin/=lib/@openzeppelin/contracts/"
],
"optimizer": {
"runs": 1000,
"enabled": true
},
"metadata": {
"bytecodeHash": "none",
"useLiteralContent": true
},
"evmVersion": "shanghai",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"addressProvider_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerIsNotMarketConfiguratorException","type":"error"},{"inputs":[{"internalType":"address","name":"degenNFT","type":"address"}],"name":"DegenNFTIsNotRegisteredException","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"ForbiddenConfigurationCallException","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"ForbiddenEmergencyConfigurationCallException","type":"error"},{"inputs":[],"name":"InvalidConstructorParamsException","type":"error"},{"inputs":[{"internalType":"address","name":"targetCotnract","type":"address"}],"name":"TargetContractIsNotAllowedException","type":"error"},{"inputs":[],"name":"addressProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"botList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bytecodeRepository","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"marketConfigurator","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"underlying","type":"address"},{"internalType":"address","name":"priceOracle","type":"address"},{"internalType":"bytes","name":"encodedParams","type":"bytes"}],"name":"computeCreditManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"name":"configure","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Call[]","name":"","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"bytes","name":"encodedParams","type":"bytes"}],"name":"deployCreditSuite","outputs":[{"components":[{"internalType":"address","name":"newContract","type":"address"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Call[]","name":"onInstallOps","type":"tuple[]"}],"internalType":"struct DeployResult","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"name":"emergencyConfigure","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Call[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketConfiguratorFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"address","name":"newLossPolicy","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"onUpdateLossPolicy","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Call[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditManager","type":"address"},{"internalType":"address","name":"newPriceOracle","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"onUpdatePriceOracle","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct Call[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
61010060405234801562000011575f80fd5b5060405162002d7138038062002d7183398101604081905262000034916200015b565b6001600160a01b03811660805280806200006f7f42595445434f44455f5245504f5349544f5259000000000000000000000000005f620000df565b6001600160a01b031660a05250620000a87f4d41524b45545f434f4e464947555241544f525f464143544f525900000000005f620000df565b6001600160a01b031660c05250620000cc671093d517d31254d560c21b5f620000df565b6001600160a01b031660e0525062000183565b608051604051632bdad0e360e11b815260048101849052602481018390525f916001600160a01b0316906357b5a1c690604401602060405180830381865afa1580156200012e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200015491906200015b565b9392505050565b5f602082840312156200016c575f80fd5b81516001600160a01b038116811462000154575f80fd5b60805160a05160c05160e051612b7b620001f65f395f818161023801526117d001525f818161016001526111c701525f81816101b101528181611e820152818161210c015281816121af015261225c01525f818161010101528181611290015281816118fd0152611f7f0152612b7b5ff3fe608060405234801561000f575f80fd5b50600436106100cf575f3560e01c806360e93cfd1161007d578063cb2ef6f711610058578063cb2ef6f7146101f9578063f605bf6c14610220578063f6722f6214610233575f80fd5b806360e93cfd146101ac5780639e6c0a8a146101d3578063b3e035b2146101e6575f80fd5b80633ecc6e7d116100ad5780633ecc6e7d1461015b5780634abf9f591461018257806354fd4d5014610195575f80fd5b80631177eee5146100d35780632954018c146100fc5780632e2ba0b01461013b575b5f80fd5b6100e66100e1366004612349565b61025a565b6040516100f39190612451565b60405180910390f35b6101237f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100f3565b61014e6101493660046124a8565b6102fd565b6040516100f391906124f9565b6101237f000000000000000000000000000000000000000000000000000000000000000081565b6100e6610190366004612349565b6105a7565b61019e61013681565b6040519081526020016100f3565b6101237f000000000000000000000000000000000000000000000000000000000000000081565b6101236101e1366004612526565b61063b565b6100e66101f43660046124a8565b610665565b61019e7f4352454449545f464143544f525900000000000000000000000000000000000081565b6100e661022e3660046124a8565b610895565b6101237f000000000000000000000000000000000000000000000000000000000000000081565b60606102f36102ee61026b866110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b039384168152825193891660248086019190915283518086039091018152604490940190925282810180516001600160e01b03167ff0b8f5620000000000000000000000000000000000000000000000000000000017905281019190915290565b611136565b90505b9392505050565b604080518082019091525f815260606020820152610319611199565b5f8061032784860186612797565b915091505f61033b33846101200151611272565b90505f61034a33898487611364565b90505f610357338361151e565b90505f610365338487611587565b6040517fe26b2f630000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301529192509085169063e26b2f63906024015f604051808303815f87803b1580156103c2575f80fd5b505af11580156103d4573d5f803e3d5ffd5b50506040517ff30ba4990000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528616925063f30ba49991506024015f604051808303815f87803b158015610431575f80fd5b505af1158015610443573d5f803e3d5ffd5b505050506040518060400160405280846001600160a01b0316815260200161059761046f3387876119b2565b61047a3388876119b2565b6040805180820182525f8082526060602092830152825180840184526001600160a01b03808c1682528451908b1660248201526044808201939093528451808203909301835260640190935280820180516001600160e01b0316630a2bf25f60e21b17905290820152610592888d60c001518e60e00151604080518082019091525f8152606060208201526040805180820182526001600160a01b038616815290516fffffffffffffffffffffffffffffffff808616602483015284166044820152602082019060640160408051601f198184030181529190526020810180516001600160e01b03167fef69768300000000000000000000000000000000000000000000000000000000179052905290509392505050565b611a41565b90529a9950505050505050505050565b60606102f36102ee6105b8866110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b039384168152825193891660248086019190915283518086039091018152604490940190925282810180516001600160e01b03167f530e784f0000000000000000000000000000000000000000000000000000000017905281019190915290565b5f8061064983850185612797565b5090506106598888888885611b05565b98975050505050505050565b60605f61067283856128c3565b90506375b51c1760e11b6001600160e01b0319821601610754575f61069a84600481886128f3565b8101906106a7919061291a565b905061074b6106b7338884611b7d565b6107466106c3896110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b039384168152825193881660248086019190915283518086039091018152604490940190925282810180516001600160e01b03167f1495c7d20000000000000000000000000000000000000000000000000000000017905281019190915290565b611c0c565b925050506102f6565b6001600160e01b031981167fbee1babf00000000000000000000000000000000000000000000000000000000148061079c57506001600160e01b031981166304828ee160e31b145b1561080a5761080260405180604001604052806107b8886110cf565b6001600160a01b0316815260200186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250611136565b9150506102f6565b7f7ba934a7000000000000000000000000000000000000000000000000000000006001600160e01b03198216016108525761080260405180604001604052806107b888611c8e565b6040517f2222fbf80000000000000000000000000000000000000000000000000000000081526001600160e01b0319821660048201526024015b60405180910390fd5b606061089f611199565b5f6108aa83856128c3565b90507fbf41d652000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610a17575f6108e7866110cf565b90505f6108f4338861151e565b9050610a0d61098183836040805180820182525f81526060602091820152815180830183526001600160a01b03948516815282519390941660248085019190915282518085039091018152604490930190915281810180517f456e0742000000000000000000000000000000000000000000000000000000006001600160e01b0390911617905282015290565b61098c338a86611b7d565b610997338b866119b2565b61059285604080518082019091525f815260606020820152506040805180820182526001600160a01b03909216825280516004815260248101909152602081810180516001600160e01b03167fef830b500000000000000000000000000000000000000000000000000000000017905282015290565b93505050506102f6565b7f28c01b51000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610b25575f610a5684600481886128f3565b810190610a639190612935565b90505f610a6f87611c8e565b90505f610a7d338985611587565b9050610b1a610aff610a8e8a6110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b03938416815282519387166024850152600160448086019190915283518086039091018152606490940190925282810180516001600160e01b0316630a2bf25f60e21b17905281019190915290565b610b0a338b86611b7d565b610b15338c866119b2565b611ccb565b9450505050506102f6565b7f325e5d8f000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610d3d575f610b6484600481886128f3565b810190610b71919061294f565b90505f610b7f338884611d6f565b90505f876001600160a01b031663fdd57645836001600160a01b031663bd90df706040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bcd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf19190612981565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610c33573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c579190612981565b90505f610c65338a84611b7d565b90505f610c73338b866119b2565b90505f610d05610c828c6110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b0393841681528251938a1660248086019190915283518086039091018152604490940190925282810180516001600160e01b03167feffa5d6e0000000000000000000000000000000000000000000000000000000017905281019190915290565b90506001600160a01b038416610d2457610d1f8282611c0c565b610d2f565b610d2f838383611ccb565b9750505050505050506102f6565b6375b51c1760e11b6001600160e01b0319821601610d63575f61069a84600481886128f3565b7fc90934da000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610eac575f80610da385600481896128f3565b810190610db0919061299c565b6040517ffdd576450000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301529294509092505f9189169063fdd5764590602401602060405180830381865afa158015610e15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e399190612981565b90506001600160a01b038116610e86576040517f32e33a4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260240161088c565b610b1a6040518060400160405280836001600160a01b0316815260200184815250611136565b6001600160e01b031981167f42f7723f000000000000000000000000000000000000000000000000000000001480610f0d57506001600160e01b031981167fb954d80900000000000000000000000000000000000000000000000000000000145b80610f4157506001600160e01b031981167f3e7c88d600000000000000000000000000000000000000000000000000000000145b80610f7557506001600160e01b031981167f3d2ff00100000000000000000000000000000000000000000000000000000000145b80610f9057506001600160e01b031981166304828ee160e31b145b80610fc457506001600160e01b031981167fb53472ef00000000000000000000000000000000000000000000000000000000145b80610ff857506001600160e01b031981167feb9606df00000000000000000000000000000000000000000000000000000000145b156110145761080260405180604001604052806107b8886110cf565b6001600160e01b031981167f8456cb5900000000000000000000000000000000000000000000000000000000148061107557506001600160e01b031981167f3f4ba83a00000000000000000000000000000000000000000000000000000000145b156110915761080260405180604001604052806107b888611c8e565b6040517fa09bfd7d0000000000000000000000000000000000000000000000000000000081526001600160e01b03198216600482015260240161088c565b5f816001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561110c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111309190612981565b92915050565b604080516001808252818301909252606091816020015b604080518082019091525f81526060602082015281526020019060019003908161114d57905050905081815f81518110611189576111896129e9565b6020026020010181905250919050565b6040517f7b731af80000000000000000000000000000000000000000000000000000000081523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690637b731af890602401602060405180830381865afa158015611214573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123891906129fd565b611270576040517f7360e36000000000000000000000000000000000000000000000000000000000815233600482015260240161088c565b565b5f80826040015180602001905181019061128c9190612981565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146112e05760405163c429e07560e01b815260040160405180910390fd5b61135c6113107f4143434f554e545f464143544f52590000000000000000000000000000000000855f0151611e27565b61013685604001518660200151886040516020016113419291909182526001600160a01b0316602082015260400190565b60405160208183030381529060405280519060200120611e32565b949350505050565b5f806113ce856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113c99190612981565b611e48565b90505f866001600160a01b0316637a0c7b216040518163ffffffff1660e01b8152600401602060405180830381865afa15801561140d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114319190612981565b6040517f2b7746f10000000000000000000000000000000000000000000000000000000081526001600160a01b0388811660048301529192505f91831690632b7746f190602401602060405180830381865afa158015611493573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114b79190612981565b90505f6114c688888489611eed565b90506115116114f57f4352454449545f4d414e4147455200000000000000000000000000000000000086611e27565b610136838c60601b6bffffffffffffffffffffffff1916611e32565b9998505050505050505050565b604080516001600160a01b03831660208201525f91829101604051602081830303815290604052905061135c7f4352454449545f434f4e464947555241544f5200000000000000000000000000610136838760601b6bffffffffffffffffffffffff1916611e32565b5f80846001600160a01b0316637a0c7b216040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e99190612981565b90505f816001600160a01b0316637db0dc19866001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611637573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061165b9190612981565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561169d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116c19190612981565b84519091506001600160a01b031615801590611784575083516040517fa37ec0280000000000000000000000000000000000000000000000000000000081527f444547454e5f4e4654000000000000000000000000000000000000000000000060048201526001600160a01b0391821660248201529087169063a37ec02890604401602060405180830381865afa15801561175e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178291906129fd565b155b156117c95783516040517fa08bb1fb0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260240161088c565b60408401517f000000000000000000000000000000000000000000000000000000000000000090156118bc575f866001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611832573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118569190612981565b9050806001600160a01b031663f6722f626040518163ffffffff1660e01b8152600401602060405180830381865afa158015611894573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b89190612981565b9150505b5f6118e77f574554485f544f4b454e000000000000000000000000000000000000000000005f611f47565b8651602080890151604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811694820194909452838d16918101919091528288166060820152828716608082015282851660a08201529190921660c082015290151560e08201529091505f906101000160405160208183030381529060405290506115117f4352454449545f46414341444500000000000000000000000000000000000000610136838c60601b6bffffffffffffffffffffffff1916611e32565b6040805180820182525f81526060602091820152815180830183526001600160a01b0395861681528251306024820152948616604486015292909416606480850191909152815180850390910181526084909301905281830180516001600160e01b03167f33598cf2000000000000000000000000000000000000000000000000000000001790529182015290565b60408051600480825260a08201909252606091816020015b604080518082019091525f815260606020820152815260200190600190039081611a5957905050905084815f81518110611a9557611a956129e9565b60200260200101819052508381600181518110611ab457611ab46129e9565b60200260200101819052508281600281518110611ad357611ad36129e9565b60200260200101819052508181600381518110611af257611af26129e9565b6020026020010181905250949350505050565b5f80611b1687846101200151611ff0565b90505f611b2286611e48565b90505f611b3188848888611eed565b9050611511611b607f4352454449545f4d414e4147455200000000000000000000000000000000000084611e27565b610136838c60601b6bffffffffffffffffffffffff19163061206a565b6040805180820182525f81526060602091820152815180830183526001600160a01b0395861681528251306024820152948616604486015292909416606480850191909152815180850390910181526084909301905281830180516001600160e01b03167f0ea26992000000000000000000000000000000000000000000000000000000001790529182015290565b6040805160028082526060828101909352816020015b604080518082019091525f815260606020820152815260200190600190039081611c2257905050905082815f81518110611c5e57611c5e6129e9565b60200260200101819052508181600181518110611c7d57611c7d6129e9565b602002602001018190525092915050565b5f816001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561110c573d5f803e3d5ffd5b60408051600380825260808201909252606091816020015b604080518082019091525f815260606020820152815260200190600190039081611ce357905050905083815f81518110611d1f57611d1f6129e9565b60200260200101819052508281600181518110611d3e57611d3e6129e9565b60200260200101819052508181600281518110611d5d57611d5d6129e9565b60200260200101819052509392505050565b5f808260400151806020019051810190611d899190612981565b9050836001600160a01b0316816001600160a01b031614611dbd5760405163c429e07560e01b815260040160405180910390fd5b611e1e611ded7f4144415054455200000000000000000000000000000000000000000000000000855f0151611e27565b61013685604001518660200151896040516020016113419291909182526001600160a01b0316602082015260400190565b95945050505050565b5f6102f6838361208b565b5f611e1e85611e4187876120d4565b858561217d565b6040517ff43876110000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063f438761190602401602060405180830381865afa158015611ec9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111309190612a18565b6060848484845f015185602001518660400151876060015188608001518960a001518a6101000151604051602001611f2e9a99989796959493929190612a2f565b6040516020818303038152906040529050949350505050565b6040517fbbd6dd6b00000000000000000000000000000000000000000000000000000000815260048101839052602481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bbd6dd6b90604401602060405180830381865afa158015611fcc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102f69190612981565b5f6102f66120217f4143434f554e545f464143544f52590000000000000000000000000000000000845f0151611e27565b61013684604001518560200151876040516020016120529291909182526001600160a01b0316602082015260400190565b60405160208183030381529060405280519060200120305b5f6120818661207988886120d4565b86868661222a565b9695505050505050565b5f81810361209a575081611130565b6102f66120a6846122d8565b6120af846122d8565b6040516020016120c0929190612aa9565b60405160208183030381529060405261230a565b6040517f4ceff70e00000000000000000000000000000000000000000000000000000000815260048101839052602481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634ceff70e90604401602060405180830381865afa158015612159573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102f69190612a18565b6040517f5ce8938f0000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635ce8938f906121ea908890889088908890600401612b00565b6020604051808303815f875af1158015612206573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e1e9190612981565b6040517ffc0dd46e0000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063fc0dd46e906122999089908990899089908990600401612b2f565b602060405180830381865afa1580156122b4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120819190612981565b6040515f5b82811a156122ed576001016122dd565b808252602082018381525f82820152505060408101604052919050565b8051602181106123215763ec92f9a35f526004601cfd5b9081015160209190910360031b1b90565b6001600160a01b0381168114612346575f80fd5b50565b5f805f6060848603121561235b575f80fd5b833561236681612332565b9250602084013561237681612332565b9150604084013561238681612332565b809150509250925092565b5f5b838110156123ab578181015183820152602001612393565b50505f910152565b5f81518084526123ca816020860160208601612391565b601f01601f19169290920160200192915050565b5f82825180855260208086019550808260051b8401018186015f5b8481101561244457858303601f19018952815180516001600160a01b031684528401516040858501819052612430818601836123b3565b9a86019a94505050908301906001016123f9565b5090979650505050505050565b602081525f6102f660208301846123de565b5f8083601f840112612473575f80fd5b50813567ffffffffffffffff81111561248a575f80fd5b6020830191508360208285010111156124a1575f80fd5b9250929050565b5f805f604084860312156124ba575f80fd5b83356124c581612332565b9250602084013567ffffffffffffffff8111156124e0575f80fd5b6124ec86828701612463565b9497909650939450505050565b602081526001600160a01b0382511660208201525f602083015160408084015261135c60608401826123de565b5f805f805f8060a0878903121561253b575f80fd5b863561254681612332565b9550602087013561255681612332565b9450604087013561256681612332565b9350606087013561257681612332565b9250608087013567ffffffffffffffff811115612591575f80fd5b61259d89828a01612463565b979a9699509497509295939492505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156125e6576125e66125af565b60405290565b604051610140810167ffffffffffffffff811182821017156125e6576125e66125af565b803560ff81168114612620575f80fd5b919050565b803561ffff81168114612620575f80fd5b80356fffffffffffffffffffffffffffffffff81168114612620575f80fd5b5f82601f830112612664575f80fd5b813567ffffffffffffffff8082111561267f5761267f6125af565b604051601f8301601f19908116603f011681019082821181831017156126a7576126a76125af565b816040528381528660208588010111156126bf575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f606082840312156126ee575f80fd5b6126f66125c3565b90508135815260208201356020820152604082013567ffffffffffffffff81111561271f575f80fd5b61272b84828501612655565b60408301525092915050565b8015158114612346575f80fd5b5f60608284031215612754575f80fd5b61275c6125c3565b9050813561276981612332565b8152602082013561277981612737565b6020820152604082013561278c81612737565b604082015292915050565b5f80608083850312156127a8575f80fd5b823567ffffffffffffffff808211156127bf575f80fd5b9084019061014082870312156127d3575f80fd5b6127db6125ec565b6127e483612610565b81526127f260208401612625565b602082015261280360408401612625565b604082015261281460608401612625565b606082015261282560808401612625565b608082015261283660a08401612625565b60a082015261284760c08401612636565b60c082015261285860e08401612636565b60e08201526101008084013583811115612870575f80fd5b61287c89828701612655565b8284015250506101208084013583811115612895575f80fd5b6128a1898287016126de565b8284015250508094505050506128ba8460208501612744565b90509250929050565b6001600160e01b031981358181169160048510156128eb5780818660040360031b1b83161692505b505092915050565b5f8085851115612901575f80fd5b8386111561290d575f80fd5b5050820193919092039150565b5f6020828403121561292a575f80fd5b81356102f681612332565b5f60608284031215612945575f80fd5b6102f68383612744565b5f6020828403121561295f575f80fd5b813567ffffffffffffffff811115612975575f80fd5b61135c848285016126de565b5f60208284031215612991575f80fd5b81516102f681612332565b5f80604083850312156129ad575f80fd5b82356129b881612332565b9150602083013567ffffffffffffffff8111156129d3575f80fd5b6129df85828601612655565b9150509250929050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612a0d575f80fd5b81516102f681612737565b5f60208284031215612a28575f80fd5b5051919050565b6001600160a01b038b811682528a811660208301528916604082015260ff8816606082015261ffff878116608083015286811660a083015285811660c083015284811660e0830152831661010082015261014061012082018190525f90612a98838201856123b3565b9d9c50505050505050505050505050565b5f8351612aba818460208801612391565b7f3a3a0000000000000000000000000000000000000000000000000000000000009083019081528351612af4816002840160208801612391565b01600201949350505050565b848152836020820152608060408201525f612b1e60808301856123b3565b905082606083015295945050505050565b85815284602082015260a060408201525f612b4d60a08301866123b3565b90508360608301526001600160a01b0383166080830152969550505050505056fea164736f6c6343000817000a000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100cf575f3560e01c806360e93cfd1161007d578063cb2ef6f711610058578063cb2ef6f7146101f9578063f605bf6c14610220578063f6722f6214610233575f80fd5b806360e93cfd146101ac5780639e6c0a8a146101d3578063b3e035b2146101e6575f80fd5b80633ecc6e7d116100ad5780633ecc6e7d1461015b5780634abf9f591461018257806354fd4d5014610195575f80fd5b80631177eee5146100d35780632954018c146100fc5780632e2ba0b01461013b575b5f80fd5b6100e66100e1366004612349565b61025a565b6040516100f39190612451565b60405180910390f35b6101237f000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e3881565b6040516001600160a01b0390911681526020016100f3565b61014e6101493660046124a8565b6102fd565b6040516100f391906124f9565b6101237f0000000000000000000000007d60cfaf7c2cec210638a5e46e4000894830c03481565b6100e6610190366004612349565b6105a7565b61019e61013681565b6040519081526020016100f3565b6101237f0000000000000000000000001ce2b1be96a082b1b1539f80d5d8f82ec06a0f9a81565b6101236101e1366004612526565b61063b565b6100e66101f43660046124a8565b610665565b61019e7f4352454449545f464143544f525900000000000000000000000000000000000081565b6100e661022e3660046124a8565b610895565b6101237f0000000000000000000000000bc03983da93021a374c964a22b73865220ce96281565b60606102f36102ee61026b866110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b039384168152825193891660248086019190915283518086039091018152604490940190925282810180516001600160e01b03167ff0b8f5620000000000000000000000000000000000000000000000000000000017905281019190915290565b611136565b90505b9392505050565b604080518082019091525f815260606020820152610319611199565b5f8061032784860186612797565b915091505f61033b33846101200151611272565b90505f61034a33898487611364565b90505f610357338361151e565b90505f610365338487611587565b6040517fe26b2f630000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301529192509085169063e26b2f63906024015f604051808303815f87803b1580156103c2575f80fd5b505af11580156103d4573d5f803e3d5ffd5b50506040517ff30ba4990000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528616925063f30ba49991506024015f604051808303815f87803b158015610431575f80fd5b505af1158015610443573d5f803e3d5ffd5b505050506040518060400160405280846001600160a01b0316815260200161059761046f3387876119b2565b61047a3388876119b2565b6040805180820182525f8082526060602092830152825180840184526001600160a01b03808c1682528451908b1660248201526044808201939093528451808203909301835260640190935280820180516001600160e01b0316630a2bf25f60e21b17905290820152610592888d60c001518e60e00151604080518082019091525f8152606060208201526040805180820182526001600160a01b038616815290516fffffffffffffffffffffffffffffffff808616602483015284166044820152602082019060640160408051601f198184030181529190526020810180516001600160e01b03167fef69768300000000000000000000000000000000000000000000000000000000179052905290509392505050565b611a41565b90529a9950505050505050505050565b60606102f36102ee6105b8866110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b039384168152825193891660248086019190915283518086039091018152604490940190925282810180516001600160e01b03167f530e784f0000000000000000000000000000000000000000000000000000000017905281019190915290565b5f8061064983850185612797565b5090506106598888888885611b05565b98975050505050505050565b60605f61067283856128c3565b90506375b51c1760e11b6001600160e01b0319821601610754575f61069a84600481886128f3565b8101906106a7919061291a565b905061074b6106b7338884611b7d565b6107466106c3896110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b039384168152825193881660248086019190915283518086039091018152604490940190925282810180516001600160e01b03167f1495c7d20000000000000000000000000000000000000000000000000000000017905281019190915290565b611c0c565b925050506102f6565b6001600160e01b031981167fbee1babf00000000000000000000000000000000000000000000000000000000148061079c57506001600160e01b031981166304828ee160e31b145b1561080a5761080260405180604001604052806107b8886110cf565b6001600160a01b0316815260200186868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250611136565b9150506102f6565b7f7ba934a7000000000000000000000000000000000000000000000000000000006001600160e01b03198216016108525761080260405180604001604052806107b888611c8e565b6040517f2222fbf80000000000000000000000000000000000000000000000000000000081526001600160e01b0319821660048201526024015b60405180910390fd5b606061089f611199565b5f6108aa83856128c3565b90507fbf41d652000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610a17575f6108e7866110cf565b90505f6108f4338861151e565b9050610a0d61098183836040805180820182525f81526060602091820152815180830183526001600160a01b03948516815282519390941660248085019190915282518085039091018152604490930190915281810180517f456e0742000000000000000000000000000000000000000000000000000000006001600160e01b0390911617905282015290565b61098c338a86611b7d565b610997338b866119b2565b61059285604080518082019091525f815260606020820152506040805180820182526001600160a01b03909216825280516004815260248101909152602081810180516001600160e01b03167fef830b500000000000000000000000000000000000000000000000000000000017905282015290565b93505050506102f6565b7f28c01b51000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610b25575f610a5684600481886128f3565b810190610a639190612935565b90505f610a6f87611c8e565b90505f610a7d338985611587565b9050610b1a610aff610a8e8a6110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b03938416815282519387166024850152600160448086019190915283518086039091018152606490940190925282810180516001600160e01b0316630a2bf25f60e21b17905281019190915290565b610b0a338b86611b7d565b610b15338c866119b2565b611ccb565b9450505050506102f6565b7f325e5d8f000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610d3d575f610b6484600481886128f3565b810190610b71919061294f565b90505f610b7f338884611d6f565b90505f876001600160a01b031663fdd57645836001600160a01b031663bd90df706040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bcd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bf19190612981565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610c33573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c579190612981565b90505f610c65338a84611b7d565b90505f610c73338b866119b2565b90505f610d05610c828c6110cf565b6040805180820182525f81526060602091820152815180830183526001600160a01b0393841681528251938a1660248086019190915283518086039091018152604490940190925282810180516001600160e01b03167feffa5d6e0000000000000000000000000000000000000000000000000000000017905281019190915290565b90506001600160a01b038416610d2457610d1f8282611c0c565b610d2f565b610d2f838383611ccb565b9750505050505050506102f6565b6375b51c1760e11b6001600160e01b0319821601610d63575f61069a84600481886128f3565b7fc90934da000000000000000000000000000000000000000000000000000000006001600160e01b0319821601610eac575f80610da385600481896128f3565b810190610db0919061299c565b6040517ffdd576450000000000000000000000000000000000000000000000000000000081526001600160a01b0380841660048301529294509092505f9189169063fdd5764590602401602060405180830381865afa158015610e15573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e399190612981565b90506001600160a01b038116610e86576040517f32e33a4f0000000000000000000000000000000000000000000000000000000081526001600160a01b038416600482015260240161088c565b610b1a6040518060400160405280836001600160a01b0316815260200184815250611136565b6001600160e01b031981167f42f7723f000000000000000000000000000000000000000000000000000000001480610f0d57506001600160e01b031981167fb954d80900000000000000000000000000000000000000000000000000000000145b80610f4157506001600160e01b031981167f3e7c88d600000000000000000000000000000000000000000000000000000000145b80610f7557506001600160e01b031981167f3d2ff00100000000000000000000000000000000000000000000000000000000145b80610f9057506001600160e01b031981166304828ee160e31b145b80610fc457506001600160e01b031981167fb53472ef00000000000000000000000000000000000000000000000000000000145b80610ff857506001600160e01b031981167feb9606df00000000000000000000000000000000000000000000000000000000145b156110145761080260405180604001604052806107b8886110cf565b6001600160e01b031981167f8456cb5900000000000000000000000000000000000000000000000000000000148061107557506001600160e01b031981167f3f4ba83a00000000000000000000000000000000000000000000000000000000145b156110915761080260405180604001604052806107b888611c8e565b6040517fa09bfd7d0000000000000000000000000000000000000000000000000000000081526001600160e01b03198216600482015260240161088c565b5f816001600160a01b031663f9aa028a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561110c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111309190612981565b92915050565b604080516001808252818301909252606091816020015b604080518082019091525f81526060602082015281526020019060019003908161114d57905050905081815f81518110611189576111896129e9565b6020026020010181905250919050565b6040517f7b731af80000000000000000000000000000000000000000000000000000000081523360048201527f0000000000000000000000007d60cfaf7c2cec210638a5e46e4000894830c0346001600160a01b031690637b731af890602401602060405180830381865afa158015611214573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123891906129fd565b611270576040517f7360e36000000000000000000000000000000000000000000000000000000000815233600482015260240161088c565b565b5f80826040015180602001905181019061128c9190612981565b90507f000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e386001600160a01b0316816001600160a01b0316146112e05760405163c429e07560e01b815260040160405180910390fd5b61135c6113107f4143434f554e545f464143544f52590000000000000000000000000000000000855f0151611e27565b61013685604001518660200151886040516020016113419291909182526001600160a01b0316602082015260400190565b60405160208183030381529060405280519060200120611e32565b949350505050565b5f806113ce856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113c99190612981565b611e48565b90505f866001600160a01b0316637a0c7b216040518163ffffffff1660e01b8152600401602060405180830381865afa15801561140d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114319190612981565b6040517f2b7746f10000000000000000000000000000000000000000000000000000000081526001600160a01b0388811660048301529192505f91831690632b7746f190602401602060405180830381865afa158015611493573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114b79190612981565b90505f6114c688888489611eed565b90506115116114f57f4352454449545f4d414e4147455200000000000000000000000000000000000086611e27565b610136838c60601b6bffffffffffffffffffffffff1916611e32565b9998505050505050505050565b604080516001600160a01b03831660208201525f91829101604051602081830303815290604052905061135c7f4352454449545f434f4e464947555241544f5200000000000000000000000000610136838760601b6bffffffffffffffffffffffff1916611e32565b5f80846001600160a01b0316637a0c7b216040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e99190612981565b90505f816001600160a01b0316637db0dc19866001600160a01b03166316f0115b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611637573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061165b9190612981565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561169d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116c19190612981565b84519091506001600160a01b031615801590611784575083516040517fa37ec0280000000000000000000000000000000000000000000000000000000081527f444547454e5f4e4654000000000000000000000000000000000000000000000060048201526001600160a01b0391821660248201529087169063a37ec02890604401602060405180830381865afa15801561175e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178291906129fd565b155b156117c95783516040517fa08bb1fb0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116600482015260240161088c565b60408401517f0000000000000000000000000bc03983da93021a374c964a22b73865220ce96290156118bc575f866001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015611832573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118569190612981565b9050806001600160a01b031663f6722f626040518163ffffffff1660e01b8152600401602060405180830381865afa158015611894573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b89190612981565b9150505b5f6118e77f574554485f544f4b454e000000000000000000000000000000000000000000005f611f47565b8651602080890151604080516001600160a01b037f000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38811694820194909452838d16918101919091528288166060820152828716608082015282851660a08201529190921660c082015290151560e08201529091505f906101000160405160208183030381529060405290506115117f4352454449545f46414341444500000000000000000000000000000000000000610136838c60601b6bffffffffffffffffffffffff1916611e32565b6040805180820182525f81526060602091820152815180830183526001600160a01b0395861681528251306024820152948616604486015292909416606480850191909152815180850390910181526084909301905281830180516001600160e01b03167f33598cf2000000000000000000000000000000000000000000000000000000001790529182015290565b60408051600480825260a08201909252606091816020015b604080518082019091525f815260606020820152815260200190600190039081611a5957905050905084815f81518110611a9557611a956129e9565b60200260200101819052508381600181518110611ab457611ab46129e9565b60200260200101819052508281600281518110611ad357611ad36129e9565b60200260200101819052508181600381518110611af257611af26129e9565b6020026020010181905250949350505050565b5f80611b1687846101200151611ff0565b90505f611b2286611e48565b90505f611b3188848888611eed565b9050611511611b607f4352454449545f4d414e4147455200000000000000000000000000000000000084611e27565b610136838c60601b6bffffffffffffffffffffffff19163061206a565b6040805180820182525f81526060602091820152815180830183526001600160a01b0395861681528251306024820152948616604486015292909416606480850191909152815180850390910181526084909301905281830180516001600160e01b03167f0ea26992000000000000000000000000000000000000000000000000000000001790529182015290565b6040805160028082526060828101909352816020015b604080518082019091525f815260606020820152815260200190600190039081611c2257905050905082815f81518110611c5e57611c5e6129e9565b60200260200101819052508181600181518110611c7d57611c7d6129e9565b602002602001018190525092915050565b5f816001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561110c573d5f803e3d5ffd5b60408051600380825260808201909252606091816020015b604080518082019091525f815260606020820152815260200190600190039081611ce357905050905083815f81518110611d1f57611d1f6129e9565b60200260200101819052508281600181518110611d3e57611d3e6129e9565b60200260200101819052508181600281518110611d5d57611d5d6129e9565b60200260200101819052509392505050565b5f808260400151806020019051810190611d899190612981565b9050836001600160a01b0316816001600160a01b031614611dbd5760405163c429e07560e01b815260040160405180910390fd5b611e1e611ded7f4144415054455200000000000000000000000000000000000000000000000000855f0151611e27565b61013685604001518660200151896040516020016113419291909182526001600160a01b0316602082015260400190565b95945050505050565b5f6102f6838361208b565b5f611e1e85611e4187876120d4565b858561217d565b6040517ff43876110000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301525f917f0000000000000000000000001ce2b1be96a082b1b1539f80d5d8f82ec06a0f9a9091169063f438761190602401602060405180830381865afa158015611ec9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111309190612a18565b6060848484845f015185602001518660400151876060015188608001518960a001518a6101000151604051602001611f2e9a99989796959493929190612a2f565b6040516020818303038152906040529050949350505050565b6040517fbbd6dd6b00000000000000000000000000000000000000000000000000000000815260048101839052602481018290525f907f000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e386001600160a01b03169063bbd6dd6b90604401602060405180830381865afa158015611fcc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102f69190612981565b5f6102f66120217f4143434f554e545f464143544f52590000000000000000000000000000000000845f0151611e27565b61013684604001518560200151876040516020016120529291909182526001600160a01b0316602082015260400190565b60405160208183030381529060405280519060200120305b5f6120818661207988886120d4565b86868661222a565b9695505050505050565b5f81810361209a575081611130565b6102f66120a6846122d8565b6120af846122d8565b6040516020016120c0929190612aa9565b60405160208183030381529060405261230a565b6040517f4ceff70e00000000000000000000000000000000000000000000000000000000815260048101839052602481018290525f907f0000000000000000000000001ce2b1be96a082b1b1539f80d5d8f82ec06a0f9a6001600160a01b031690634ceff70e90604401602060405180830381865afa158015612159573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102f69190612a18565b6040517f5ce8938f0000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000001ce2b1be96a082b1b1539f80d5d8f82ec06a0f9a1690635ce8938f906121ea908890889088908890600401612b00565b6020604051808303815f875af1158015612206573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e1e9190612981565b6040517ffc0dd46e0000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000001ce2b1be96a082b1b1539f80d5d8f82ec06a0f9a169063fc0dd46e906122999089908990899089908990600401612b2f565b602060405180830381865afa1580156122b4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120819190612981565b6040515f5b82811a156122ed576001016122dd565b808252602082018381525f82820152505060408101604052919050565b8051602181106123215763ec92f9a35f526004601cfd5b9081015160209190910360031b1b90565b6001600160a01b0381168114612346575f80fd5b50565b5f805f6060848603121561235b575f80fd5b833561236681612332565b9250602084013561237681612332565b9150604084013561238681612332565b809150509250925092565b5f5b838110156123ab578181015183820152602001612393565b50505f910152565b5f81518084526123ca816020860160208601612391565b601f01601f19169290920160200192915050565b5f82825180855260208086019550808260051b8401018186015f5b8481101561244457858303601f19018952815180516001600160a01b031684528401516040858501819052612430818601836123b3565b9a86019a94505050908301906001016123f9565b5090979650505050505050565b602081525f6102f660208301846123de565b5f8083601f840112612473575f80fd5b50813567ffffffffffffffff81111561248a575f80fd5b6020830191508360208285010111156124a1575f80fd5b9250929050565b5f805f604084860312156124ba575f80fd5b83356124c581612332565b9250602084013567ffffffffffffffff8111156124e0575f80fd5b6124ec86828701612463565b9497909650939450505050565b602081526001600160a01b0382511660208201525f602083015160408084015261135c60608401826123de565b5f805f805f8060a0878903121561253b575f80fd5b863561254681612332565b9550602087013561255681612332565b9450604087013561256681612332565b9350606087013561257681612332565b9250608087013567ffffffffffffffff811115612591575f80fd5b61259d89828a01612463565b979a9699509497509295939492505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff811182821017156125e6576125e66125af565b60405290565b604051610140810167ffffffffffffffff811182821017156125e6576125e66125af565b803560ff81168114612620575f80fd5b919050565b803561ffff81168114612620575f80fd5b80356fffffffffffffffffffffffffffffffff81168114612620575f80fd5b5f82601f830112612664575f80fd5b813567ffffffffffffffff8082111561267f5761267f6125af565b604051601f8301601f19908116603f011681019082821181831017156126a7576126a76125af565b816040528381528660208588010111156126bf575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f606082840312156126ee575f80fd5b6126f66125c3565b90508135815260208201356020820152604082013567ffffffffffffffff81111561271f575f80fd5b61272b84828501612655565b60408301525092915050565b8015158114612346575f80fd5b5f60608284031215612754575f80fd5b61275c6125c3565b9050813561276981612332565b8152602082013561277981612737565b6020820152604082013561278c81612737565b604082015292915050565b5f80608083850312156127a8575f80fd5b823567ffffffffffffffff808211156127bf575f80fd5b9084019061014082870312156127d3575f80fd5b6127db6125ec565b6127e483612610565b81526127f260208401612625565b602082015261280360408401612625565b604082015261281460608401612625565b606082015261282560808401612625565b608082015261283660a08401612625565b60a082015261284760c08401612636565b60c082015261285860e08401612636565b60e08201526101008084013583811115612870575f80fd5b61287c89828701612655565b8284015250506101208084013583811115612895575f80fd5b6128a1898287016126de565b8284015250508094505050506128ba8460208501612744565b90509250929050565b6001600160e01b031981358181169160048510156128eb5780818660040360031b1b83161692505b505092915050565b5f8085851115612901575f80fd5b8386111561290d575f80fd5b5050820193919092039150565b5f6020828403121561292a575f80fd5b81356102f681612332565b5f60608284031215612945575f80fd5b6102f68383612744565b5f6020828403121561295f575f80fd5b813567ffffffffffffffff811115612975575f80fd5b61135c848285016126de565b5f60208284031215612991575f80fd5b81516102f681612332565b5f80604083850312156129ad575f80fd5b82356129b881612332565b9150602083013567ffffffffffffffff8111156129d3575f80fd5b6129df85828601612655565b9150509250929050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612a0d575f80fd5b81516102f681612737565b5f60208284031215612a28575f80fd5b5051919050565b6001600160a01b038b811682528a811660208301528916604082015260ff8816606082015261ffff878116608083015286811660a083015285811660c083015284811660e0830152831661010082015261014061012082018190525f90612a98838201856123b3565b9d9c50505050505050505050505050565b5f8351612aba818460208801612391565b7f3a3a0000000000000000000000000000000000000000000000000000000000009083019081528351612af4816002840160208801612391565b01600201949350505050565b848152836020820152608060408201525f612b1e60808301856123b3565b905082606083015295945050505050565b85815284602082015260a060408201525f612b4d60a08301866123b3565b90508360608301526001600160a01b0383166080830152969550505050505056fea164736f6c6343000817000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38
-----Decoded View---------------
Arg [0] : addressProvider_ (address): 0xF7f0a609BfAb9a0A98786951ef10e5FE26cC1E38
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MON
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.