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 | 73 days ago | Contract Creation | 0 MON |
Loading...
Loading
Contract Name:
MarketConfiguratorFactory
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 {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IContractsRegister} from "../interfaces/IContractsRegister.sol";
import {IMarketConfigurator} from "../interfaces/IMarketConfigurator.sol";
import {IMarketConfiguratorFactory} from "../interfaces/IMarketConfiguratorFactory.sol";
import {
AP_CROSS_CHAIN_GOVERNANCE,
AP_MARKET_CONFIGURATOR,
AP_MARKET_CONFIGURATOR_FACTORY,
NO_VERSION_CONTROL
} from "../libraries/ContractLiterals.sol";
import {DeployerTrait} from "../traits/DeployerTrait.sol";
/// @title Market configurator factory
contract MarketConfiguratorFactory is DeployerTrait, IMarketConfiguratorFactory {
using EnumerableSet for EnumerableSet.AddressSet;
/// @notice Contract version
uint256 public constant override version = 3_10;
/// @notice Contract type
bytes32 public constant override contractType = AP_MARKET_CONFIGURATOR_FACTORY;
/// @dev Set of registered market configurators
EnumerableSet.AddressSet internal _registeredMarketConfiguratorsSet;
/// @dev Set of shutdown market configurators
EnumerableSet.AddressSet internal _shutdownMarketConfiguratorsSet;
/// @dev Reverts if caller is not cross-chain governance
modifier onlyCrossChainGovernance() {
if (msg.sender != _getAddressOrRevert(AP_CROSS_CHAIN_GOVERNANCE, NO_VERSION_CONTROL)) {
revert CallerIsNotCrossChainGovernanceException(msg.sender);
}
_;
}
/// @dev Reverts if `msg.sender` is not the admin of `marketConfigurator`
modifier onlyMarketConfiguratorAdmin(address marketConfigurator) {
if (msg.sender != IMarketConfigurator(marketConfigurator).admin()) {
revert CallerIsNotMarketConfiguratorAdminException(msg.sender);
}
_;
}
/// @notice Constructor
/// @param addressProvider_ Address provider contract address
constructor(address addressProvider_) DeployerTrait(addressProvider_) {}
// ------- //
// GETTERS //
// ------- //
/// @notice Returns whether `account` is a registered market configurator
function isMarketConfigurator(address account) external view override returns (bool) {
return _registeredMarketConfiguratorsSet.contains(account);
}
/// @notice Returns all registered market configurators
function getMarketConfigurators() external view override returns (address[] memory) {
return _registeredMarketConfiguratorsSet.values();
}
/// @notice Returns the market configurator at `index`
function getMarketConfigurator(uint256 index) external view override returns (address) {
return _registeredMarketConfiguratorsSet.at(index);
}
/// @notice Returns the number of registered market configurators
function getNumMarketConfigurators() external view override returns (uint256) {
return _registeredMarketConfiguratorsSet.length();
}
/// @notice Returns all shutdown market configurators
function getShutdownMarketConfigurators() external view override returns (address[] memory) {
return _shutdownMarketConfiguratorsSet.values();
}
// ------------- //
// CONFIGURATION //
// ------------- //
/// @notice Allows anyone to permissionlessly deploy a new market configurator
/// @param emergencyAdmin Address to set as emergency admin
/// @param adminFeeTreasury Address to set as the second admin of the fee splitter, with the first one being the
/// DAO treasury. If `address(0)`, the splitter is not deployed and all fees will be sent to the treasury.
/// @param curatorName Risk curator name
/// @param deployGovernor If true, a governor contract is deployed and set as market configurator's admin.
/// `msg.sender` is set as its owner, queue and execution admin, while `emergencyAdmin` is set as veto admin.
/// Otherwise, `msg.sender` is set as the admin of the market configurator.
/// @return marketConfigurator Address of the newly deployed market configurator
function createMarketConfigurator(
address emergencyAdmin,
address adminFeeTreasury,
string calldata curatorName,
bool deployGovernor
) external override returns (address marketConfigurator) {
marketConfigurator = _deployLatestPatch({
contractType: AP_MARKET_CONFIGURATOR,
minorVersion: 3_10,
constructorParams: abi.encode(
addressProvider, msg.sender, emergencyAdmin, adminFeeTreasury, curatorName, deployGovernor
),
salt: bytes32(bytes20(msg.sender))
});
_registeredMarketConfiguratorsSet.add(marketConfigurator);
emit CreateMarketConfigurator(marketConfigurator, curatorName);
}
/// @notice Allows the admin of `marketConfigurator` to shut it down
/// @dev Reverts if caller is not the admin of `marketConfigurator`
/// @dev Reverts if `marketConfigurator` is not registered or already shutdown
/// @dev Reverts if `marketConfigurator` has non-shutdown pools
function shutdownMarketConfigurator(address marketConfigurator)
external
override
onlyMarketConfiguratorAdmin(marketConfigurator)
{
if (!_shutdownMarketConfiguratorsSet.add(marketConfigurator)) {
revert MarketConfiguratorIsAlreadyShutdownException(marketConfigurator);
}
if (!_registeredMarketConfiguratorsSet.remove(marketConfigurator)) {
revert MarketConfiguratorIsNotRegisteredException(marketConfigurator);
}
address contractsRegister = IMarketConfigurator(marketConfigurator).contractsRegister();
if (IContractsRegister(contractsRegister).getPools().length != 0) {
revert CantShutdownMarketConfiguratorException(marketConfigurator);
}
emit ShutdownMarketConfigurator(marketConfigurator);
}
/// @notice Allows cross-chain governance to register an externally deployed legacy market configurator
/// @dev Reverts if caller is not cross-chain governance
/// @dev Reverts if `marketConfigurator` is already registered or shutdown
function addMarketConfigurator(address marketConfigurator) external override onlyCrossChainGovernance {
if (!_registeredMarketConfiguratorsSet.add(marketConfigurator)) {
revert MarketConfiguratorIsAlreadyAddedException(marketConfigurator);
}
if (_shutdownMarketConfiguratorsSet.contains(marketConfigurator)) {
revert MarketConfiguratorIsAlreadyShutdownException(marketConfigurator);
}
emit CreateMarketConfigurator(marketConfigurator, IMarketConfigurator(marketConfigurator).curatorName());
}
}// 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: 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; 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 {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 {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
// 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
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
// 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
// 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;
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);
}{
"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":"CallerIsNotCrossChainGovernanceException","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerIsNotMarketConfiguratorAdminException","type":"error"},{"inputs":[{"internalType":"address","name":"marketConfigurator","type":"address"}],"name":"CantShutdownMarketConfiguratorException","type":"error"},{"inputs":[{"internalType":"address","name":"marketConfigurator","type":"address"}],"name":"MarketConfiguratorIsAlreadyAddedException","type":"error"},{"inputs":[{"internalType":"address","name":"marketConfigruator","type":"address"}],"name":"MarketConfiguratorIsAlreadyShutdownException","type":"error"},{"inputs":[{"internalType":"address","name":"marketConfigurator","type":"address"}],"name":"MarketConfiguratorIsNotRegisteredException","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketConfigurator","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"CreateMarketConfigurator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketConfigurator","type":"address"}],"name":"ShutdownMarketConfigurator","type":"event"},{"inputs":[{"internalType":"address","name":"marketConfigurator","type":"address"}],"name":"addMarketConfigurator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addressProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bytecodeRepository","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"emergencyAdmin","type":"address"},{"internalType":"address","name":"adminFeeTreasury","type":"address"},{"internalType":"string","name":"curatorName","type":"string"},{"internalType":"bool","name":"deployGovernor","type":"bool"}],"name":"createMarketConfigurator","outputs":[{"internalType":"address","name":"marketConfigurator","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getMarketConfigurator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMarketConfigurators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumMarketConfigurators","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getShutdownMarketConfigurators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isMarketConfigurator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"marketConfigurator","type":"address"}],"name":"shutdownMarketConfigurator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60c060405234801561000f575f80fd5b5060405161113c38038061113c83398101604081905261002e916100f3565b6001600160a01b038116608052806100667f42595445434f44455f5245504f5349544f5259000000000000000000000000005f61007a565b6001600160a01b031660a052506101199050565b608051604051632bdad0e360e11b815260048101849052602481018390525f916001600160a01b0316906357b5a1c690604401602060405180830381865afa1580156100c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100ec91906100f3565b9392505050565b5f60208284031215610103575f80fd5b81516001600160a01b03811681146100ec575f80fd5b60805160a051610fe76101555f395f8181610163015281816108b3015261095601525f818160f30152818161024b015261080a0152610fe75ff3fe608060405234801561000f575f80fd5b50600436106100cf575f3560e01c80637b731af81161007d578063cb2ef6f711610058578063cb2ef6f7146101d0578063cee2840e146101f7578063e6ff34101461020a575f80fd5b80637b731af8146101855780639fb7385a146101a8578063b5845f9d146101bd575f80fd5b806339dd6e1d116100ad57806339dd6e1d1461014057806354fd4d501461015557806360e93cfd1461015e575f80fd5b806322ab7bb5146100d35780632954018c146100ee5780633400e0331461012d575b5f80fd5b6100db610212565b6040519081526020015b60405180910390f35b6101157f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100e5565b61011561013b366004610b96565b610221565b61015361014e366004610c3f565b610306565b005b6100db61013681565b6101157f000000000000000000000000000000000000000000000000000000000000000081565b610198610193366004610c3f565b610576565b60405190151581526020016100e5565b6101b0610587565b6040516100e59190610c5a565b6101156101cb366004610ca6565b610592565b6100db7f4d41524b45545f434f4e464947555241544f525f464143544f5259000000000081565b610153610205366004610c3f565b61059d565b6101b0610737565b5f61021c5f610743565b905090565b5f6102ad7f4d41524b45545f434f4e464947555241544f52000000000000000000000000006101367f0000000000000000000000000000000000000000000000000000000000000000338a8a8a8a8a6040516020016102869796959493929190610ce5565b6040516020818303038152906040523360601b6bffffffffffffffffffffffff191661074c565b90506102b95f8261076b565b50806001600160a01b03167f43fa48b4a55fef538f40ed78ec7b1c1e16027e8127ef4a8e8f0078eb8bdafb1485856040516102f5929190610d37565b60405180910390a295945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610343573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103679190610d52565b6001600160a01b0316336001600160a01b0316146103b8576040517fc76395450000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6103c360028361076b565b6103eb57604051635ce5af0560e11b81526001600160a01b03831660048201526024016103af565b6103f55f83610786565b610436576040517f092669b60000000000000000000000000000000000000000000000000000000081526001600160a01b03831660048201526024016103af565b5f826001600160a01b0316637a0c7b216040518163ffffffff1660e01b8152600401602060405180830381865afa158015610473573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104979190610d52565b9050806001600160a01b031663673a2a1f6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156104d4573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104fb9190810190610db2565b511561053e576040517f239f65e60000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016103af565b6040516001600160a01b038416907f57fe0f922fda8c4b08c2b9d5e4584c5f5c673a38b6480036d4b94e5cb0118099905f90a2505050565b5f610581818361079a565b92915050565b606061021c5f6107bb565b5f61058181836107c7565b6105c77f43524f53535f434841494e5f474f5645524e414e4345000000000000000000005f6107d2565b6001600160a01b0316336001600160a01b031614610613576040517fbcb63d190000000000000000000000000000000000000000000000000000000081523360048201526024016103af565b61061d5f8261076b565b61065e576040517fa12e59b10000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016103af565b61066960028261079a565b1561069257604051635ce5af0560e11b81526001600160a01b03821660048201526024016103af565b806001600160a01b03167f43fa48b4a55fef538f40ed78ec7b1c1e16027e8127ef4a8e8f0078eb8bdafb14826001600160a01b031663c9470abd6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156106f8573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261071f9190810190610e81565b60405161072c9190610f3b565b60405180910390a250565b606061021c60026107bb565b5f610581825490565b5f6107628561075b878761087b565b8585610924565b95945050505050565b5f61077f836001600160a01b0384166109d1565b9392505050565b5f61077f836001600160a01b038416610a1d565b6001600160a01b0381165f908152600183016020526040812054151561077f565b60605f61077f83610b00565b5f61077f8383610b59565b6040517f57b5a1c600000000000000000000000000000000000000000000000000000000815260048101839052602481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906357b5a1c690604401602060405180830381865afa158015610857573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077f9190610d52565b6040517f4ceff70e00000000000000000000000000000000000000000000000000000000815260048101839052602481018290525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634ceff70e90604401602060405180830381865afa158015610900573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077f9190610f4d565b6040517f5ce8938f0000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635ce8938f90610991908890889088908890600401610f64565b6020604051808303815f875af11580156109ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107629190610d52565b5f818152600183016020526040812054610a1657508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610581565b505f610581565b5f8181526001830160205260408120548015610af7575f610a3f600183610f93565b85549091505f90610a5290600190610f93565b9050818114610ab1575f865f018281548110610a7057610a70610fb2565b905f5260205f200154905080875f018481548110610a9057610a90610fb2565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080610ac257610ac2610fc6565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610581565b5f915050610581565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610b4d57602002820191905f5260205f20905b815481526020019060010190808311610b39575b50505050509050919050565b5f825f018281548110610b6e57610b6e610fb2565b905f5260205f200154905092915050565b6001600160a01b0381168114610b93575f80fd5b50565b5f805f805f60808688031215610baa575f80fd5b8535610bb581610b7f565b94506020860135610bc581610b7f565b9350604086013567ffffffffffffffff80821115610be1575f80fd5b818801915088601f830112610bf4575f80fd5b813581811115610c02575f80fd5b896020828501011115610c13575f80fd5b60208301955080945050505060608601358015158114610c31575f80fd5b809150509295509295909350565b5f60208284031215610c4f575f80fd5b813561077f81610b7f565b602080825282518282018190525f9190848201906040850190845b81811015610c9a5783516001600160a01b031683529284019291840191600101610c75565b50909695505050505050565b5f60208284031215610cb6575f80fd5b5035919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f6001600160a01b03808a1683528089166020840152808816604084015280871660608401525060c06080830152610d2160c083018587610cbd565b905082151560a083015298975050505050505050565b602081525f610d4a602083018486610cbd565b949350505050565b5f60208284031215610d62575f80fd5b815161077f81610b7f565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610daa57610daa610d6d565b604052919050565b5f6020808385031215610dc3575f80fd5b825167ffffffffffffffff80821115610dda575f80fd5b818501915085601f830112610ded575f80fd5b815181811115610dff57610dff610d6d565b8060051b9150610e10848301610d81565b8181529183018401918481019088841115610e29575f80fd5b938501935b83851015610e535784519250610e4383610b7f565b8282529385019390850190610e2e565b98975050505050505050565b5f5b83811015610e79578181015183820152602001610e61565b50505f910152565b5f60208284031215610e91575f80fd5b815167ffffffffffffffff80821115610ea8575f80fd5b818401915084601f830112610ebb575f80fd5b815181811115610ecd57610ecd610d6d565b610ee0601f8201601f1916602001610d81565b9150808252856020828501011115610ef6575f80fd5b610f07816020840160208601610e5f565b50949350505050565b5f8151808452610f27816020860160208601610e5f565b601f01601f19169290920160200192915050565b602081525f61077f6020830184610f10565b5f60208284031215610f5d575f80fd5b5051919050565b848152836020820152608060408201525f610f826080830185610f10565b905082606083015295945050505050565b8181038181111561058157634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea164736f6c6343000817000a000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100cf575f3560e01c80637b731af81161007d578063cb2ef6f711610058578063cb2ef6f7146101d0578063cee2840e146101f7578063e6ff34101461020a575f80fd5b80637b731af8146101855780639fb7385a146101a8578063b5845f9d146101bd575f80fd5b806339dd6e1d116100ad57806339dd6e1d1461014057806354fd4d501461015557806360e93cfd1461015e575f80fd5b806322ab7bb5146100d35780632954018c146100ee5780633400e0331461012d575b5f80fd5b6100db610212565b6040519081526020015b60405180910390f35b6101157f000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e3881565b6040516001600160a01b0390911681526020016100e5565b61011561013b366004610b96565b610221565b61015361014e366004610c3f565b610306565b005b6100db61013681565b6101157f0000000000000000000000001ce2b1be96a082b1b1539f80d5d8f82ec06a0f9a81565b610198610193366004610c3f565b610576565b60405190151581526020016100e5565b6101b0610587565b6040516100e59190610c5a565b6101156101cb366004610ca6565b610592565b6100db7f4d41524b45545f434f4e464947555241544f525f464143544f5259000000000081565b610153610205366004610c3f565b61059d565b6101b0610737565b5f61021c5f610743565b905090565b5f6102ad7f4d41524b45545f434f4e464947555241544f52000000000000000000000000006101367f000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38338a8a8a8a8a6040516020016102869796959493929190610ce5565b6040516020818303038152906040523360601b6bffffffffffffffffffffffff191661074c565b90506102b95f8261076b565b50806001600160a01b03167f43fa48b4a55fef538f40ed78ec7b1c1e16027e8127ef4a8e8f0078eb8bdafb1485856040516102f5929190610d37565b60405180910390a295945050505050565b80806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610343573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103679190610d52565b6001600160a01b0316336001600160a01b0316146103b8576040517fc76395450000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6103c360028361076b565b6103eb57604051635ce5af0560e11b81526001600160a01b03831660048201526024016103af565b6103f55f83610786565b610436576040517f092669b60000000000000000000000000000000000000000000000000000000081526001600160a01b03831660048201526024016103af565b5f826001600160a01b0316637a0c7b216040518163ffffffff1660e01b8152600401602060405180830381865afa158015610473573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104979190610d52565b9050806001600160a01b031663673a2a1f6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156104d4573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526104fb9190810190610db2565b511561053e576040517f239f65e60000000000000000000000000000000000000000000000000000000081526001600160a01b03841660048201526024016103af565b6040516001600160a01b038416907f57fe0f922fda8c4b08c2b9d5e4584c5f5c673a38b6480036d4b94e5cb0118099905f90a2505050565b5f610581818361079a565b92915050565b606061021c5f6107bb565b5f61058181836107c7565b6105c77f43524f53535f434841494e5f474f5645524e414e4345000000000000000000005f6107d2565b6001600160a01b0316336001600160a01b031614610613576040517fbcb63d190000000000000000000000000000000000000000000000000000000081523360048201526024016103af565b61061d5f8261076b565b61065e576040517fa12e59b10000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016103af565b61066960028261079a565b1561069257604051635ce5af0560e11b81526001600160a01b03821660048201526024016103af565b806001600160a01b03167f43fa48b4a55fef538f40ed78ec7b1c1e16027e8127ef4a8e8f0078eb8bdafb14826001600160a01b031663c9470abd6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156106f8573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261071f9190810190610e81565b60405161072c9190610f3b565b60405180910390a250565b606061021c60026107bb565b5f610581825490565b5f6107628561075b878761087b565b8585610924565b95945050505050565b5f61077f836001600160a01b0384166109d1565b9392505050565b5f61077f836001600160a01b038416610a1d565b6001600160a01b0381165f908152600183016020526040812054151561077f565b60605f61077f83610b00565b5f61077f8383610b59565b6040517f57b5a1c600000000000000000000000000000000000000000000000000000000815260048101839052602481018290525f907f000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e386001600160a01b0316906357b5a1c690604401602060405180830381865afa158015610857573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077f9190610d52565b6040517f4ceff70e00000000000000000000000000000000000000000000000000000000815260048101839052602481018290525f907f0000000000000000000000001ce2b1be96a082b1b1539f80d5d8f82ec06a0f9a6001600160a01b031690634ceff70e90604401602060405180830381865afa158015610900573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077f9190610f4d565b6040517f5ce8938f0000000000000000000000000000000000000000000000000000000081525f906001600160a01b037f0000000000000000000000001ce2b1be96a082b1b1539f80d5d8f82ec06a0f9a1690635ce8938f90610991908890889088908890600401610f64565b6020604051808303815f875af11580156109ad573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107629190610d52565b5f818152600183016020526040812054610a1657508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610581565b505f610581565b5f8181526001830160205260408120548015610af7575f610a3f600183610f93565b85549091505f90610a5290600190610f93565b9050818114610ab1575f865f018281548110610a7057610a70610fb2565b905f5260205f200154905080875f018481548110610a9057610a90610fb2565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080610ac257610ac2610fc6565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610581565b5f915050610581565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610b4d57602002820191905f5260205f20905b815481526020019060010190808311610b39575b50505050509050919050565b5f825f018281548110610b6e57610b6e610fb2565b905f5260205f200154905092915050565b6001600160a01b0381168114610b93575f80fd5b50565b5f805f805f60808688031215610baa575f80fd5b8535610bb581610b7f565b94506020860135610bc581610b7f565b9350604086013567ffffffffffffffff80821115610be1575f80fd5b818801915088601f830112610bf4575f80fd5b813581811115610c02575f80fd5b896020828501011115610c13575f80fd5b60208301955080945050505060608601358015158114610c31575f80fd5b809150509295509295909350565b5f60208284031215610c4f575f80fd5b813561077f81610b7f565b602080825282518282018190525f9190848201906040850190845b81811015610c9a5783516001600160a01b031683529284019291840191600101610c75565b50909695505050505050565b5f60208284031215610cb6575f80fd5b5035919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f6001600160a01b03808a1683528089166020840152808816604084015280871660608401525060c06080830152610d2160c083018587610cbd565b905082151560a083015298975050505050505050565b602081525f610d4a602083018486610cbd565b949350505050565b5f60208284031215610d62575f80fd5b815161077f81610b7f565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610daa57610daa610d6d565b604052919050565b5f6020808385031215610dc3575f80fd5b825167ffffffffffffffff80821115610dda575f80fd5b818501915085601f830112610ded575f80fd5b815181811115610dff57610dff610d6d565b8060051b9150610e10848301610d81565b8181529183018401918481019088841115610e29575f80fd5b938501935b83851015610e535784519250610e4383610b7f565b8282529385019390850190610e2e565b98975050505050505050565b5f5b83811015610e79578181015183820152602001610e61565b50505f910152565b5f60208284031215610e91575f80fd5b815167ffffffffffffffff80821115610ea8575f80fd5b818401915084601f830112610ebb575f80fd5b815181811115610ecd57610ecd610d6d565b610ee0601f8201601f1916602001610d81565b9150808252856020828501011115610ef6575f80fd5b610f07816020840160208601610e5f565b50949350505050565b5f8151808452610f27816020860160208601610e5f565b601f01601f19169290920160200192915050565b602081525f61077f6020830184610f10565b5f60208284031215610f5d575f80fd5b5051919050565b848152836020820152608060408201525f610f826080830185610f10565b905082606083015295945050505050565b8181038181111561058157634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea164736f6c6343000817000a
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.