Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
HinkalMiddleware
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 4096 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.27; // import { Time } from "@openzeppelin/contracts/utils/types/Time.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { IVaultConfigurator } from "@symbioticfi/core/src/interfaces/IVaultConfigurator.sol"; import { IVault } from "@symbioticfi/core/src/interfaces/vault/IVault.sol"; import { IOptInService } from "@symbioticfi/core/src/interfaces/service/IOptInService.sol"; import { IEntity } from "@symbioticfi/core/src/interfaces/common/IEntity.sol"; import { ISlasher } from "@symbioticfi/core/src/interfaces/slasher/ISlasher.sol"; import { IVetoSlasher } from "@symbioticfi/core/src/interfaces/slasher/IVetoSlasher.sol"; import { IRegistry } from "@symbioticfi/core/src/interfaces/common/IRegistry.sol"; import { IBaseDelegator } from "@symbioticfi/core/src/interfaces/delegator/IBaseDelegator.sol"; import { IFullRestakeDelegator, IBaseDelegator } from "@symbioticfi/core/src/interfaces/delegator/IFullRestakeDelegator.sol"; import { INetworkRestakeDelegator } from "@symbioticfi/core/src/interfaces/delegator/INetworkRestakeDelegator.sol"; import { Subnetwork } from "@symbioticfi/core/src/contracts/libraries/Subnetwork.sol"; interface IHinkalHelper { function isRelayInList(address relay) external view returns (bool); } interface IHinkalMiddleware { function isValidOperator(address operator) external view returns (bool); function relayer() external view returns (address); } contract HinkalMiddleware is IHinkalMiddleware, Initializable, EIP712Upgradeable, OwnableUpgradeable { using EnumerableSet for EnumerableSet.AddressSet; using Subnetwork for address; error SlashingWindowTooShort(); error UnknownSlasherType(); error NotNetwork(); error OperatorVaultAlreadySetted(); error OperatorAlreadyRegistred(); error NotOperator(); error OperatorNotOptedIn(); error OperatorIsBlacklisted(); error OperatorNotRegistred(); error OperatorAlreadyEnabled(); error OperatorAlreadyDisabled(); error OperatorAlreadyBlacklisted(); error TooBigSlashAmount(); error NotWhitelistedEndpoint(); error NotSignedByNetwork(); error InvalidNonce(); error InvalidDeadline(); event OperatorAndVaultSet(address indexed operator, address indexed vault); event OperatorEnabled(address indexed operator, bool indexed enable); event OperatorBlacklisted(address indexed operator, bool indexed blacklist); // immutables address public NETWORK; address public OPERATOR_REGISTRY; // address public VAULT_REGISTRY; address public OPERATOR_NET_OPTIN; address public OPERATOR_VAULT_OPTIN; address public VAULT_CONFIGURATOR; uint48 private constant INSTANT_SLASHER_TYPE = 0; uint48 private constant VETO_SLASHER_TYPE = 1; uint64 public constant VAULT_VERSION = 1; // added uint48 public VAULT_EPOCH_DURATION; address public COLLATERAL; address public relayer; address public hinkalHelper; uint256 public minimumStake; // TODO: maybe next variables need some restrucutre uint256 public constant SLASH_PERCENT_MAX = 10000; uint256 public slashPercent; EnumerableSet.AddressSet private operators; mapping(address => OperatorInfo) public operatorInfos; AddOperatorAndVaultParams public defaultVaultParams; mapping(address => bool) public isWhitelistedEndpoint; mapping(uint256 => bool) public nonces; struct OperatorInfo { address vault; bool enabled; bool isBlacklisted; } struct VaultInitParams { bool depositWhitelist; bool isDepositLimit; uint256 depositLimit; address burner; address depositWhitelistSetRoleHolder; address depositorWhitelistRoleHolder; address isDepositLimitSetRoleHolder; address depositLimitSetRoleHolder; } struct SlasherInitParams { uint64 slasherIndex; uint48 vetoDuration; uint256 resolverSetEpochsDelay; } struct DelegatorInitParams { uint64 delegatorIndex; address hookSetRoleHolder; address hook; } struct AddOperatorAndVaultParams { VaultInitParams vaultInitParams; SlasherInitParams slasherInitParams; DelegatorInitParams delegatorInitParams; } function initialize( address _network, address _operatorRegistry, address _operatorNetOptin, address _operatorVaultOptin, address _vaultConfigurator, address _collateral, address _hinkalHelper, uint48 _vaultEpochDuration, uint256 _minimumStake, uint256 _slashPercent, AddOperatorAndVaultParams calldata _defaultVaultParams ) external initializer { __Ownable_init(msg.sender); __EIP712_init_unchained("HinkalMiddleware", "1"); NETWORK = _network; COLLATERAL = _collateral; OPERATOR_REGISTRY = _operatorRegistry; VAULT_EPOCH_DURATION = _vaultEpochDuration; VAULT_CONFIGURATOR = _vaultConfigurator; OPERATOR_NET_OPTIN = _operatorNetOptin; OPERATOR_VAULT_OPTIN = _operatorVaultOptin; minimumStake = _minimumStake; slashPercent = _slashPercent; hinkalHelper = _hinkalHelper; defaultVaultParams = _defaultVaultParams; relayer = address(1); } modifier setRelayerForHinkal() { // TODO: needs review relayer = tx.origin; _; relayer = address(1); } modifier onlyOperator() { require(IHinkalHelper(hinkalHelper).isRelayInList(tx.origin) || isValidOperator(tx.origin)); _; } modifier onlyNetwork() { require(msg.sender == NETWORK, NotNetwork()); _; } function isValidOperator(address operator) public view virtual returns (bool) { address vault = operatorInfos[operator].vault; require(vault != address(0), OperatorNotRegistred()); uint256 stake = IBaseDelegator(IVault(vault).delegator()).stake( NETWORK.subnetwork(0), operator ); return stake >= minimumStake; } function registerOperator(address operator) external virtual onlyOwner { require(operatorInfos[operator].vault == address(0), OperatorVaultAlreadySetted()); // other stuff require(!operators.contains(operator), OperatorAlreadyRegistred()); require(IRegistry(OPERATOR_REGISTRY).isEntity(operator), NotOperator()); require(IOptInService(OPERATOR_NET_OPTIN).isOptedIn(operator, NETWORK), OperatorNotOptedIn()); bytes memory vaultInitParams = abi.encode( IVault.InitParams({ collateral: COLLATERAL, burner: defaultVaultParams.vaultInitParams.burner, epochDuration: VAULT_EPOCH_DURATION, depositWhitelist: defaultVaultParams.vaultInitParams.depositWhitelist, isDepositLimit: defaultVaultParams.vaultInitParams.isDepositLimit, depositLimit: defaultVaultParams.vaultInitParams.depositLimit, defaultAdminRoleHolder: owner(), depositWhitelistSetRoleHolder: defaultVaultParams .vaultInitParams .depositWhitelistSetRoleHolder, depositorWhitelistRoleHolder: defaultVaultParams .vaultInitParams .depositorWhitelistRoleHolder, isDepositLimitSetRoleHolder: defaultVaultParams.vaultInitParams.isDepositLimitSetRoleHolder, depositLimitSetRoleHolder: defaultVaultParams.vaultInitParams.depositLimitSetRoleHolder }) ); address[] memory networkSetterRoles = new address[](2); networkSetterRoles[0] = address(this); networkSetterRoles[1] = owner(); bytes memory delegatorParams = abi.encode( IFullRestakeDelegator.InitParams({ baseParams: IBaseDelegator.BaseParams({ defaultAdminRoleHolder: owner(), hook: defaultVaultParams.delegatorInitParams.hook, hookSetRoleHolder: defaultVaultParams.delegatorInitParams.hookSetRoleHolder }), networkLimitSetRoleHolders: networkSetterRoles, operatorNetworkLimitSetRoleHolders: networkSetterRoles }) ); bytes memory slahserParams = defaultVaultParams.slasherInitParams.slasherIndex == 0 ? new bytes(0) : abi.encode( IVetoSlasher.InitParams({ vetoDuration: defaultVaultParams.slasherInitParams.vetoDuration, resolverSetEpochsDelay: defaultVaultParams.slasherInitParams.resolverSetEpochsDelay }) ); IVaultConfigurator.InitParams memory configuratorParams = IVaultConfigurator.InitParams({ version: VAULT_VERSION, owner: owner(), vaultParams: vaultInitParams, delegatorIndex: defaultVaultParams.delegatorInitParams.delegatorIndex, delegatorParams: delegatorParams, withSlasher: true, slasherIndex: defaultVaultParams.slasherInitParams.slasherIndex, slasherParams: slahserParams }); (address vault, , ) = IVaultConfigurator(VAULT_CONFIGURATOR).create( configuratorParams ); operatorInfos[operator].vault = vault; // IFullRestakeDelegator(delegator).setNetworkLimit(NETWORK.subnetwork(0), type(uint256).max); // IFullRestakeDelegator(delegator).setOperatorNetworkLimit( // NETWORK.subnetwork(0), // operator, // type(uint256).max // ); emit OperatorAndVaultSet(operator, vault); } function setOperatorState(address operator) public virtual { OperatorInfo storage operatorInfo = operatorInfos[operator]; require(operators.contains(operator), NotOperator()); require(!operatorInfo.isBlacklisted, OperatorIsBlacklisted()); require( IOptInService(OPERATOR_VAULT_OPTIN).isOptedIn(operator, operatorInfo.vault), OperatorNotOptedIn() ); uint256 opStake = IBaseDelegator(IVault(operatorInfo.vault).delegator()).stake( NETWORK.subnetwork(0), operator ); if (opStake >= minimumStake) { // require(!operatorInfo.enabled, OperatorAlreadyEnabled()); operators.add(operator); IFullRestakeDelegator(IVault(operatorInfo.vault).delegator()).setOperatorNetworkLimit( NETWORK.subnetwork(0), operator, type(uint256).max ); operatorInfo.enabled = true; emit OperatorEnabled(operator, true); } else { // require(operatorInfo.enabled, OperatorAlreadyDisabled()); operators.remove(operator); IFullRestakeDelegator(IVault(operatorInfo.vault).delegator()).setOperatorNetworkLimit( NETWORK.subnetwork(0), operator, 0 ); operatorInfo.enabled = false; emit OperatorEnabled(operator, false); } } // TODO: maybe onlyNetwork() function blacklistOperator(address operator, bool blacklist) external virtual onlyOwner { OperatorInfo storage operatorInfo = operatorInfos[operator]; if (blacklist) { require(!operatorInfo.isBlacklisted, OperatorAlreadyBlacklisted()); operatorInfo.isBlacklisted = true; if (operators.contains(operator)) { operators.remove(operator); emit OperatorEnabled(operator, false); } } else { require(operatorInfo.isBlacklisted, OperatorAlreadyEnabled()); operatorInfo.isBlacklisted = false; } emit OperatorBlacklisted(operator, blacklist); } function setWhitelistedEndpoint(address endpoint, bool val) external virtual onlyOwner { isWhitelistedEndpoint[endpoint] = val; } function setHinkalHelper(address newHinkalHelper) external virtual onlyOwner { hinkalHelper = newHinkalHelper; } function slash(address operator) external virtual onlyNetwork { uint256 amount = (getOperatorStake(operator) * slashPercent) / SLASH_PERCENT_MAX; _slash(operator, amount); } function slashAmount(address operator, uint256 amount) external virtual onlyNetwork { _slash(operator, amount); } function _slash(address operator, uint256 amount) internal virtual { uint256 totalOperatorStake = getOperatorStake(operator); require(totalOperatorStake >= amount, TooBigSlashAmount()); address vault = operatorInfos[operator].vault; _slashVault(uint48(block.timestamp), vault, NETWORK.subnetwork(0), operator, amount); uint256 stake = totalOperatorStake - amount; if (stake < minimumStake) { operators.remove(operator); IFullRestakeDelegator(IVault(vault).delegator()).setOperatorNetworkLimit( NETWORK.subnetwork(0), operator, 0 ); operatorInfos[operator].enabled = false; } } function getOperatorStake(address operator) public view virtual returns (uint256 stake) { address vault = operatorInfos[operator].vault; stake = IBaseDelegator(IVault(vault).delegator()).stake(NETWORK.subnetwork(0), operator); return stake; } function execute( address endpoint, uint256 nonce, uint48 deadline, bytes memory paylod, bytes memory signature ) external payable onlyOperator setRelayerForHinkal { bytes32 structHash = keccak256(abi.encode(tx.origin, endpoint, nonce, deadline, paylod)); bytes32 hash = _hashTypedDataV4(structHash); require(!nonces[nonce], InvalidNonce()); require(deadline < uint48(block.timestamp), InvalidDeadline()); require(ECDSA.recover(hash, signature) == NETWORK, NotSignedByNetwork()); require(isWhitelistedEndpoint[endpoint], NotWhitelistedEndpoint()); Address.functionCallWithValue(endpoint, paylod, msg.value); nonces[nonce] = true; } function _slashVault( uint48 timestamp, address vault, bytes32 subnetwork, address operator, uint256 amount ) internal virtual { address slasher = IVault(vault).slasher(); uint256 slasherType = IEntity(slasher).TYPE(); require(slasherType < 2, UnknownSlasherType()); if (slasherType == INSTANT_SLASHER_TYPE) { ISlasher(slasher).slash(subnetwork, operator, amount, timestamp, new bytes(0)); } else { IVetoSlasher(slasher).requestSlash(subnetwork, operator, amount, timestamp, new bytes(0)); } } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } receive() external payable {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.20; import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {IERC5267} from "@openzeppelin/contracts/interfaces/IERC5267.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. */ abstract contract EIP712Upgradeable is Initializable, IERC5267 { bytes32 private constant TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); /// @custom:storage-location erc7201:openzeppelin.storage.EIP712 struct EIP712Storage { /// @custom:oz-renamed-from _HASHED_NAME bytes32 _hashedName; /// @custom:oz-renamed-from _HASHED_VERSION bytes32 _hashedVersion; string _name; string _version; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.EIP712")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant EIP712StorageLocation = 0xa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100; function _getEIP712Storage() private pure returns (EIP712Storage storage $) { assembly { $.slot := EIP712StorageLocation } } /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing { EIP712Storage storage $ = _getEIP712Storage(); $._name = name; $._version = version; // Reset prior values in storage if upgrading $._hashedName = 0; $._hashedVersion = 0; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(); } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {IERC-5267}. */ function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { EIP712Storage storage $ = _getEIP712Storage(); // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized // and the EIP712 domain is not reliable, as it will be missing name and version. require($._hashedName == 0 && $._hashedVersion == 0, "EIP712: Uninitialized"); return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Name() internal view virtual returns (string memory) { EIP712Storage storage $ = _getEIP712Storage(); return $._name; } /** * @dev The version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Version() internal view virtual returns (string memory) { EIP712Storage storage $ = _getEIP712Storage(); return $._version; } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead. */ function _EIP712NameHash() internal view returns (bytes32) { EIP712Storage storage $ = _getEIP712Storage(); string memory name = _EIP712Name(); if (bytes(name).length > 0) { return keccak256(bytes(name)); } else { // If the name is empty, the contract may have been upgraded without initializing the new storage. // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design. bytes32 hashedName = $._hashedName; if (hashedName != 0) { return hashedName; } else { return keccak256(""); } } } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead. */ function _EIP712VersionHash() internal view returns (bytes32) { EIP712Storage storage $ = _getEIP712Storage(); string memory version = _EIP712Version(); if (bytes(version).length > 0) { return keccak256(bytes(version)); } else { // If the version is empty, the contract may have been upgraded without initializing the new storage. // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design. bytes32 hashedVersion = $._hashedVersion; if (hashedVersion != 0) { return hashedVersion; } else { return keccak256(""); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.20; interface IERC5267 { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @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 is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @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._positions[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 cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 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 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[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._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This library adds functions to work with subnetworks. */ library Subnetwork { function subnetwork(address network_, uint96 identifier_) internal pure returns (bytes32) { return bytes32(uint256(uint160(network_)) << 96 | identifier_); } function network( bytes32 subnetwork_ ) internal pure returns (address) { return address(uint160(uint256(subnetwork_ >> 96))); } function identifier( bytes32 subnetwork_ ) internal pure returns (uint96) { return uint96(uint256(subnetwork_)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IEntity { error NotInitialized(); /** * @notice Get the factory's address. * @return address of the factory */ function FACTORY() external view returns (address); /** * @notice Get the entity's type. * @return type of the entity */ function TYPE() external view returns (uint64); /** * @notice Initialize this entity contract by using a given data. * @param data some data to use */ function initialize( bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IMigratableEntity { error AlreadyInitialized(); error NotFactory(); error NotInitialized(); /** * @notice Get the factory's address. * @return address of the factory */ function FACTORY() external view returns (address); /** * @notice Get the entity's version. * @return version of the entity * @dev Starts from 1. */ function version() external view returns (uint64); /** * @notice Initialize this entity contract by using a given data and setting a particular version and owner. * @param initialVersion initial version of the entity * @param owner initial owner of the entity * @param data some data to use */ function initialize(uint64 initialVersion, address owner, bytes calldata data) external; /** * @notice Migrate this entity to a particular newer version using a given data. * @param newVersion new version of the entity * @param data some data to use */ function migrate(uint64 newVersion, bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IRegistry { error EntityNotExist(); /** * @notice Emitted when an entity is added. * @param entity address of the added entity */ event AddEntity(address indexed entity); /** * @notice Get if a given address is an entity. * @param account address to check * @return if the given address is an entity */ function isEntity( address account ) external view returns (bool); /** * @notice Get a total number of entities. * @return total number of entities added */ function totalEntities() external view returns (uint256); /** * @notice Get an entity given its index. * @param index index of the entity to get * @return address of the entity */ function entity( uint256 index ) external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IEntity} from "../common/IEntity.sol"; interface IBaseDelegator is IEntity { error AlreadySet(); error InsufficientHookGas(); error NotNetwork(); error NotSlasher(); error NotVault(); /** * @notice Base parameters needed for delegators' deployment. * @param defaultAdminRoleHolder address of the initial DEFAULT_ADMIN_ROLE holder * @param hook address of the hook contract * @param hookSetRoleHolder address of the initial HOOK_SET_ROLE holder */ struct BaseParams { address defaultAdminRoleHolder; address hook; address hookSetRoleHolder; } /** * @notice Base hints for a stake. * @param operatorVaultOptInHint hint for the operator-vault opt-in * @param operatorNetworkOptInHint hint for the operator-network opt-in */ struct StakeBaseHints { bytes operatorVaultOptInHint; bytes operatorNetworkOptInHint; } /** * @notice Emitted when a subnetwork's maximum limit is set. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param amount new maximum subnetwork's limit (how much stake the subnetwork is ready to get) */ event SetMaxNetworkLimit(bytes32 indexed subnetwork, uint256 amount); /** * @notice Emitted when a slash happened. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param slashedAmount amount of the collateral slashed */ event OnSlash(bytes32 indexed subnetwork, address indexed operator, uint256 slashedAmount); /** * @notice Emitted when a hook is set. * @param hook address of the hook */ event SetHook(address indexed hook); /** * @notice Get a version of the delegator (different versions mean different interfaces). * @return version of the delegator * @dev Must return 1 for this one. */ function VERSION() external view returns (uint64); /** * @notice Get the network registry's address. * @return address of the network registry */ function NETWORK_REGISTRY() external view returns (address); /** * @notice Get the vault factory's address. * @return address of the vault factory */ function VAULT_FACTORY() external view returns (address); /** * @notice Get the operator-vault opt-in service's address. * @return address of the operator-vault opt-in service */ function OPERATOR_VAULT_OPT_IN_SERVICE() external view returns (address); /** * @notice Get the operator-network opt-in service's address. * @return address of the operator-network opt-in service */ function OPERATOR_NETWORK_OPT_IN_SERVICE() external view returns (address); /** * @notice Get a gas limit for the hook. * @return value of the hook gas limit */ function HOOK_GAS_LIMIT() external view returns (uint256); /** * @notice Get a reserve gas between the gas limit check and the hook's execution. * @return value of the reserve gas */ function HOOK_RESERVE() external view returns (uint256); /** * @notice Get a hook setter's role. * @return identifier of the hook setter role */ function HOOK_SET_ROLE() external view returns (bytes32); /** * @notice Get the vault's address. * @return address of the vault */ function vault() external view returns (address); /** * @notice Get the hook's address. * @return address of the hook * @dev The hook can have arbitrary logic under certain functions, however, it doesn't affect the stake guarantees. */ function hook() external view returns (address); /** * @notice Get a particular subnetwork's maximum limit * (meaning the subnetwork is not ready to get more as a stake). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @return maximum limit of the subnetwork */ function maxNetworkLimit( bytes32 subnetwork ) external view returns (uint256); /** * @notice Get a stake that a given subnetwork could be able to slash for a certain operator at a given timestamp * until the end of the consequent epoch using hints (if no cross-slashing and no slashings by the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param timestamp time point to capture the stake at * @param hints hints for the checkpoints' indexes * @return slashable stake at the given timestamp until the end of the consequent epoch * @dev Warning: it is not safe to use timestamp >= current one for the stake capturing, as it can change later. */ function stakeAt( bytes32 subnetwork, address operator, uint48 timestamp, bytes memory hints ) external view returns (uint256); /** * @notice Get a stake that a given subnetwork will be able to slash * for a certain operator until the end of the next epoch (if no cross-slashing and no slashings by the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @return slashable stake until the end of the next epoch * @dev Warning: this function is not safe to use for stake capturing, as it can change by the end of the block. */ function stake(bytes32 subnetwork, address operator) external view returns (uint256); /** * @notice Set a maximum limit for a subnetwork (how much stake the subnetwork is ready to get). * identifier identifier of the subnetwork * @param amount new maximum subnetwork's limit * @dev Only a network can call this function. */ function setMaxNetworkLimit(uint96 identifier, uint256 amount) external; /** * @notice Set a new hook. * @param hook address of the hook * @dev Only a HOOK_SET_ROLE holder can call this function. * The hook can have arbitrary logic under certain functions, however, it doesn't affect the stake guarantees. */ function setHook( address hook ) external; /** * @notice Called when a slash happens. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param slashedAmount amount of the collateral slashed * @param captureTimestamp time point when the stake was captured * @param data some additional data * @dev Only the vault's slasher can call this function. */ function onSlash( bytes32 subnetwork, address operator, uint256 slashedAmount, uint48 captureTimestamp, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IBaseDelegator} from "./IBaseDelegator.sol"; interface IFullRestakeDelegator is IBaseDelegator { error DuplicateRoleHolder(); error ExceedsMaxNetworkLimit(); error MissingRoleHolders(); error ZeroAddressRoleHolder(); /** * @notice Hints for a stake. * @param baseHints base hints * @param activeStakeHint hint for the active stake checkpoint * @param networkLimitHint hint for the subnetwork limit checkpoint * @param operatorNetworkLimitHint hint for the operator-subnetwork limit checkpoint */ struct StakeHints { bytes baseHints; bytes activeStakeHint; bytes networkLimitHint; bytes operatorNetworkLimitHint; } /** * @notice Initial parameters needed for a full restaking delegator deployment. * @param baseParams base parameters for delegators' deployment * @param networkLimitSetRoleHolders array of addresses of the initial NETWORK_LIMIT_SET_ROLE holders * @param operatorNetworkLimitSetRoleHolders array of addresses of the initial OPERATOR_NETWORK_LIMIT_SET_ROLE holders */ struct InitParams { IBaseDelegator.BaseParams baseParams; address[] networkLimitSetRoleHolders; address[] operatorNetworkLimitSetRoleHolders; } /** * @notice Emitted when a subnetwork's limit is set. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param amount new subnetwork's limit (how much stake the vault curator is ready to give to the subnetwork) */ event SetNetworkLimit(bytes32 indexed subnetwork, uint256 amount); /** * @notice Emitted when an operator's limit for a subnetwork is set. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param amount new operator's limit for the subnetwork * (how much stake the vault curator is ready to give to the operator for the subnetwork) */ event SetOperatorNetworkLimit(bytes32 indexed subnetwork, address indexed operator, uint256 amount); /** * @notice Get a subnetwork limit setter's role. * @return identifier of the subnetwork limit setter role */ function NETWORK_LIMIT_SET_ROLE() external view returns (bytes32); /** * @notice Get an operator-subnetwork limit setter's role. * @return identifier of the operator-subnetwork limit setter role */ function OPERATOR_NETWORK_LIMIT_SET_ROLE() external view returns (bytes32); /** * @notice Get a subnetwork's limit at a given timestamp using a hint * (how much stake the vault curator is ready to give to the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param timestamp time point to get the subnetwork limit at * @param hint hint for checkpoint index * @return limit of the subnetwork at the given timestamp */ function networkLimitAt(bytes32 subnetwork, uint48 timestamp, bytes memory hint) external view returns (uint256); /** * @notice Get a subnetwork's limit (how much stake the vault curator is ready to give to the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @return limit of the subnetwork */ function networkLimit( bytes32 subnetwork ) external view returns (uint256); /** * @notice Get an operator's limit for a subnetwork at a given timestamp using a hint * (how much stake the vault curator is ready to give to the operator for the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param timestamp time point to get the operator's limit for the subnetwork at * @param hint hint for checkpoint index * @return limit of the operator for the subnetwork at the given timestamp */ function operatorNetworkLimitAt( bytes32 subnetwork, address operator, uint48 timestamp, bytes memory hint ) external view returns (uint256); /** * @notice Get an operator's limit for a subnetwork. * (how much stake the vault curator is ready to give to the operator for the subnetwork) * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @return limit of the operator for the subnetwork */ function operatorNetworkLimit(bytes32 subnetwork, address operator) external view returns (uint256); /** * @notice Set a subnetwork's limit (how much stake the vault curator is ready to give to the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param amount new limit of the subnetwork * @dev Only a NETWORK_LIMIT_SET_ROLE holder can call this function. */ function setNetworkLimit(bytes32 subnetwork, uint256 amount) external; /** * @notice Set an operator's limit for a subnetwork. * (how much stake the vault curator is ready to give to the operator for the subnetwork) * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param amount new limit of the operator for the subnetwork * @dev Only an OPERATOR_NETWORK_LIMIT_SET_ROLE holder can call this function. */ function setOperatorNetworkLimit(bytes32 subnetwork, address operator, uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IBaseDelegator} from "./IBaseDelegator.sol"; interface INetworkRestakeDelegator is IBaseDelegator { error DuplicateRoleHolder(); error ExceedsMaxNetworkLimit(); error MissingRoleHolders(); error ZeroAddressRoleHolder(); /** * @notice Hints for a stake. * @param baseHints base hints * @param activeStakeHint hint for the active stake checkpoint * @param networkLimitHint hint for the subnetwork limit checkpoint * @param totalOperatorNetworkSharesHint hint for the total operator-subnetwork shares checkpoint * @param operatorNetworkSharesHint hint for the operator-subnetwork shares checkpoint */ struct StakeHints { bytes baseHints; bytes activeStakeHint; bytes networkLimitHint; bytes totalOperatorNetworkSharesHint; bytes operatorNetworkSharesHint; } /** * @notice Initial parameters needed for a full restaking delegator deployment. * @param baseParams base parameters for delegators' deployment * @param networkLimitSetRoleHolders array of addresses of the initial NETWORK_LIMIT_SET_ROLE holders * @param operatorNetworkSharesSetRoleHolders array of addresses of the initial OPERATOR_NETWORK_SHARES_SET_ROLE holders */ struct InitParams { IBaseDelegator.BaseParams baseParams; address[] networkLimitSetRoleHolders; address[] operatorNetworkSharesSetRoleHolders; } /** * @notice Emitted when a subnetwork's limit is set. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param amount new subnetwork's limit (how much stake the vault curator is ready to give to the subnetwork) */ event SetNetworkLimit(bytes32 indexed subnetwork, uint256 amount); /** * @notice Emitted when an operator's shares inside a subnetwork are set. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param shares new operator's shares inside the subnetwork (what percentage, * which is equal to the shares divided by the total operators' shares, * of the subnetwork's stake the vault curator is ready to give to the operator) */ event SetOperatorNetworkShares(bytes32 indexed subnetwork, address indexed operator, uint256 shares); /** * @notice Get a subnetwork limit setter's role. * @return identifier of the subnetwork limit setter role */ function NETWORK_LIMIT_SET_ROLE() external view returns (bytes32); /** * @notice Get an operator-subnetwork shares setter's role. * @return identifier of the operator-subnetwork shares setter role */ function OPERATOR_NETWORK_SHARES_SET_ROLE() external view returns (bytes32); /** * @notice Get a subnetwork's limit at a given timestamp using a hint * (how much stake the vault curator is ready to give to the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param timestamp time point to get the subnetwork limit at * @param hint hint for checkpoint index * @return limit of the subnetwork at the given timestamp */ function networkLimitAt(bytes32 subnetwork, uint48 timestamp, bytes memory hint) external view returns (uint256); /** * @notice Get a subnetwork's limit (how much stake the vault curator is ready to give to the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @return limit of the subnetwork */ function networkLimit( bytes32 subnetwork ) external view returns (uint256); /** * @notice Get a sum of operators' shares for a subnetwork at a given timestamp using a hint. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param timestamp time point to get the total operators' shares at * @param hint hint for checkpoint index * @return total shares of the operators for the subnetwork at the given timestamp */ function totalOperatorNetworkSharesAt( bytes32 subnetwork, uint48 timestamp, bytes memory hint ) external view returns (uint256); /** * @notice Get a sum of operators' shares for a subnetwork. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @return total shares of the operators for the subnetwork */ function totalOperatorNetworkShares( bytes32 subnetwork ) external view returns (uint256); /** * @notice Get an operator's shares for a subnetwork at a given timestamp using a hint (what percentage, * which is equal to the shares divided by the total operators' shares, * of the subnetwork's stake the vault curator is ready to give to the operator). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param timestamp time point to get the operator's shares at * @param hint hint for checkpoint index * @return shares of the operator for the subnetwork at the given timestamp */ function operatorNetworkSharesAt( bytes32 subnetwork, address operator, uint48 timestamp, bytes memory hint ) external view returns (uint256); /** * @notice Get an operator's shares for a subnetwork (what percentage, * which is equal to the shares divided by the total operators' shares, * of the subnetwork's stake the vault curator is ready to give to the operator). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @return shares of the operator for the subnetwork */ function operatorNetworkShares(bytes32 subnetwork, address operator) external view returns (uint256); /** * @notice Set a subnetwork's limit (how much stake the vault curator is ready to give to the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param amount new limit of the subnetwork * @dev Only a NETWORK_LIMIT_SET_ROLE holder can call this function. */ function setNetworkLimit(bytes32 subnetwork, uint256 amount) external; /** * @notice Set an operator's shares for a subnetwork (what percentage, * which is equal to the shares divided by the total operators' shares, * of the subnetwork's stake the vault curator is ready to give to the operator). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param shares new shares of the operator for the subnetwork * @dev Only an OPERATOR_NETWORK_SHARES_SET_ROLE holder can call this function. */ function setOperatorNetworkShares(bytes32 subnetwork, address operator, uint256 shares) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IVaultConfigurator { error DirtyInitParams(); /** * @notice Initial parameters needed for a vault with a delegator and a slasher deployment. * @param version entity's version to use * @param owner initial owner of the entity * @param vaultParams parameters for the vault initialization * @param delegatorIndex delegator's index of the implementation to deploy * @param delegatorParams parameters for the delegator initialization * @param withSlasher whether to deploy a slasher or not * @param slasherIndex slasher's index of the implementation to deploy (used only if withSlasher == true) * @param slasherParams parameters for the slasher initialization (used only if withSlasher == true) */ struct InitParams { uint64 version; address owner; bytes vaultParams; uint64 delegatorIndex; bytes delegatorParams; bool withSlasher; uint64 slasherIndex; bytes slasherParams; } /** * @notice Get the vault factory's address. * @return address of the vault factory */ function VAULT_FACTORY() external view returns (address); /** * @notice Get the delegator factory's address. * @return address of the delegator factory */ function DELEGATOR_FACTORY() external view returns (address); /** * @notice Get the slasher factory's address. * @return address of the slasher factory */ function SLASHER_FACTORY() external view returns (address); /** * @notice Create a new vault with a delegator and a slasher. * @param params initial parameters needed for a vault with a delegator and a slasher deployment * @return vault address of the vault * @return delegator address of the delegator * @return slasher address of the slasher */ function create( InitParams calldata params ) external returns (address vault, address delegator, address slasher); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IOptInService { error AlreadyOptedIn(); error NotOptedIn(); error NotWhereEntity(); error NotWho(); error OptOutCooldown(); /** * @notice Emitted when a "who" opts into a "where" entity. * @param who address of the "who" * @param where address of the "where" entity */ event OptIn(address indexed who, address indexed where); /** * @notice Emitted when a "who" opts out from a "where" entity. * @param who address of the "who" * @param where address of the "where" entity */ event OptOut(address indexed who, address indexed where); /** * @notice Get the "who" registry's address. * @return address of the "who" registry */ function WHO_REGISTRY() external view returns (address); /** * @notice Get the address of the registry where to opt-in. * @return address of the "where" registry */ function WHERE_REGISTRY() external view returns (address); /** * @notice Get if a given "who" is opted-in to a particular "where" entity at a given timestamp using a hint. * @param who address of the "who" * @param where address of the "where" registry * @param timestamp time point to get if the "who" is opted-in at * @param hint hint for the checkpoint index * @return if the "who" is opted-in at the given timestamp */ function isOptedInAt( address who, address where, uint48 timestamp, bytes calldata hint ) external view returns (bool); /** * @notice Check if a given "who" is opted-in to a particular "where" entity. * @param who address of the "who" * @param where address of the "where" registry * @return if the "who" is opted-in */ function isOptedIn(address who, address where) external view returns (bool); /** * @notice Opt-in a calling "who" to a particular "where" entity. * @param where address of the "where" registry */ function optIn( address where ) external; /** * @notice Opt-out a calling "who" from a particular "where" entity. * @param where address of the "where" registry */ function optOut( address where ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ISlasher { error InsufficientSlash(); error InvalidCaptureTimestamp(); /** * @notice Hints for a slash. * @param slashableStakeHints hints for the slashable stake checkpoints */ struct SlashHints { bytes slashableStakeHints; } /** * @notice Emitted when a slash is performed. * @param subnetwork subnetwork that requested the slash * @param operator operator that is slashed * @param slashedAmount amount of the collateral slashed * @param captureTimestamp time point when the stake was captured */ event Slash(bytes32 indexed subnetwork, address indexed operator, uint256 slashedAmount, uint48 captureTimestamp); /** * @notice Perform a slash using a subnetwork for a particular operator by a given amount using hints. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param amount maximum amount of the collateral to be slashed * @param captureTimestamp time point when the stake was captured * @param hints hints for checkpoints' indexes * @return slashedAmount amount of the collateral slashed * @dev Only a network middleware can call this function. */ function slash( bytes32 subnetwork, address operator, uint256 amount, uint48 captureTimestamp, bytes calldata hints ) external returns (uint256 slashedAmount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IVetoSlasher { error InsufficientSlash(); error InvalidCaptureTimestamp(); error InvalidResolverSetEpochsDelay(); error InvalidVetoDuration(); error NoResolver(); error NotNetwork(); error NotResolver(); error SlashPeriodEnded(); error SlashRequestCompleted(); error SlashRequestNotExist(); error VaultNotInitialized(); error VetoPeriodEnded(); error VetoPeriodNotEnded(); /** * @notice Initial parameters needed for a slasher deployment. * @param vetoDuration duration of the veto period for a slash request * @param resolverSetEpochsDelay delay in epochs for a network to update a resolver */ struct InitParams { uint48 vetoDuration; uint256 resolverSetEpochsDelay; } /** * @notice Structure for a slash request. * @param subnetwork subnetwork that requested the slash * @param operator operator that could be slashed (if the request is not vetoed) * @param amount maximum amount of the collateral to be slashed * @param captureTimestamp time point when the stake was captured * @param vetoDeadline deadline for the resolver to veto the slash (exclusively) * @param completed if the slash was vetoed/executed */ struct SlashRequest { bytes32 subnetwork; address operator; uint256 amount; uint48 captureTimestamp; uint48 vetoDeadline; bool completed; } /** * @notice Hints for a slash request. * @param slashableStakeHints hints for the slashable stake checkpoints */ struct RequestSlashHints { bytes slashableStakeHints; } /** * @notice Hints for a slash execute. * @param captureResolverHint hint for the resolver checkpoint at the capture time * @param currentResolverHint hint for the resolver checkpoint at the current time * @param slashableStakeHints hints for the slashable stake checkpoints */ struct ExecuteSlashHints { bytes captureResolverHint; bytes currentResolverHint; bytes slashableStakeHints; } /** * @notice Hints for a slash veto. * @param captureResolverHint hint for the resolver checkpoint at the capture time * @param currentResolverHint hint for the resolver checkpoint at the current time */ struct VetoSlashHints { bytes captureResolverHint; bytes currentResolverHint; } /** * @notice Hints for a resolver set. * @param resolverHint hint for the resolver checkpoint */ struct SetResolverHints { bytes resolverHint; } /** * @notice Emitted when a slash request is created. * @param slashIndex index of the slash request * @param subnetwork subnetwork that requested the slash * @param operator operator that could be slashed (if the request is not vetoed) * @param slashAmount maximum amount of the collateral to be slashed * @param captureTimestamp time point when the stake was captured * @param vetoDeadline deadline for the resolver to veto the slash (exclusively) */ event RequestSlash( uint256 indexed slashIndex, bytes32 indexed subnetwork, address indexed operator, uint256 slashAmount, uint48 captureTimestamp, uint48 vetoDeadline ); /** * @notice Emitted when a slash request is executed. * @param slashIndex index of the slash request * @param slashedAmount amount of the collateral slashed */ event ExecuteSlash(uint256 indexed slashIndex, uint256 slashedAmount); /** * @notice Emitted when a slash request is vetoed. * @param slashIndex index of the slash request * @param resolver address of the resolver that vetoed the slash */ event VetoSlash(uint256 indexed slashIndex, address indexed resolver); /** * @notice Emitted when a resolver is set. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param resolver address of the resolver */ event SetResolver(bytes32 indexed subnetwork, address resolver); /** * @notice Get the network registry's address. * @return address of the network registry */ function NETWORK_REGISTRY() external view returns (address); /** * @notice Get a duration during which resolvers can veto slash requests. * @return duration of the veto period */ function vetoDuration() external view returns (uint48); /** * @notice Get a total number of slash requests. * @return total number of slash requests */ function slashRequestsLength() external view returns (uint256); /** * @notice Get a particular slash request. * @param slashIndex index of the slash request * @return subnetwork subnetwork that requested the slash * @return operator operator that could be slashed (if the request is not vetoed) * @return amount maximum amount of the collateral to be slashed * @return captureTimestamp time point when the stake was captured * @return vetoDeadline deadline for the resolver to veto the slash (exclusively) * @return completed if the slash was vetoed/executed */ function slashRequests( uint256 slashIndex ) external view returns ( bytes32 subnetwork, address operator, uint256 amount, uint48 captureTimestamp, uint48 vetoDeadline, bool completed ); /** * @notice Get a delay for networks in epochs to update a resolver. * @return updating resolver delay in epochs */ function resolverSetEpochsDelay() external view returns (uint256); /** * @notice Get a resolver for a given subnetwork at a particular timestamp using a hint. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param timestamp timestamp to get the resolver at * @param hints hints for the checkpoint index * @return address of the resolver */ function resolverAt(bytes32 subnetwork, uint48 timestamp, bytes memory hints) external view returns (address); /** * @notice Get a resolver for a given subnetwork using a hint. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param hint hint for the checkpoint index * @return address of the resolver */ function resolver(bytes32 subnetwork, bytes memory hint) external view returns (address); /** * @notice Request a slash using a subnetwork for a particular operator by a given amount using hints. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param amount maximum amount of the collateral to be slashed * @param captureTimestamp time point when the stake was captured * @param hints hints for checkpoints' indexes * @return slashIndex index of the slash request * @dev Only a network middleware can call this function. */ function requestSlash( bytes32 subnetwork, address operator, uint256 amount, uint48 captureTimestamp, bytes calldata hints ) external returns (uint256 slashIndex); /** * @notice Execute a slash with a given slash index using hints. * @param slashIndex index of the slash request * @param hints hints for checkpoints' indexes * @return slashedAmount amount of the collateral slashed * @dev Only a network middleware can call this function. */ function executeSlash(uint256 slashIndex, bytes calldata hints) external returns (uint256 slashedAmount); /** * @notice Veto a slash with a given slash index using hints. * @param slashIndex index of the slash request * @param hints hints for checkpoints' indexes * @dev Only a resolver can call this function. */ function vetoSlash(uint256 slashIndex, bytes calldata hints) external; /** * @notice Set a resolver for a subnetwork using hints. * identifier identifier of the subnetwork * @param resolver address of the resolver * @param hints hints for checkpoints' indexes * @dev Only a network can call this function. */ function setResolver(uint96 identifier, address resolver, bytes calldata hints) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IMigratableEntity} from "../common/IMigratableEntity.sol"; import {IVaultStorage} from "./IVaultStorage.sol"; interface IVault is IMigratableEntity, IVaultStorage { error AlreadyClaimed(); error AlreadySet(); error DelegatorAlreadyInitialized(); error DepositLimitReached(); error InsufficientClaim(); error InsufficientDeposit(); error InsufficientRedemption(); error InsufficientWithdrawal(); error InvalidAccount(); error InvalidCaptureEpoch(); error InvalidClaimer(); error InvalidCollateral(); error InvalidDelegator(); error InvalidEpoch(); error InvalidEpochDuration(); error InvalidLengthEpochs(); error InvalidOnBehalfOf(); error InvalidRecipient(); error InvalidSlasher(); error MissingRoles(); error NoDepositLimit(); error NoDepositWhitelist(); error NotDelegator(); error NotSlasher(); error NotWhitelistedDepositor(); error SlasherAlreadyInitialized(); error TooMuchRedeem(); error TooMuchWithdraw(); /** * @notice Initial parameters needed for a vault deployment. * @param collateral vault's underlying collateral * @param burner vault's burner to issue debt to (e.g., 0xdEaD or some unwrapper contract) * @param epochDuration duration of the vault epoch (it determines sync points for withdrawals) * @param depositWhitelist if enabling deposit whitelist * @param isDepositLimit if enabling deposit limit * @param depositLimit deposit limit (maximum amount of the collateral that can be in the vault simultaneously) * @param defaultAdminRoleHolder address of the initial DEFAULT_ADMIN_ROLE holder * @param depositWhitelistSetRoleHolder address of the initial DEPOSIT_WHITELIST_SET_ROLE holder * @param depositorWhitelistRoleHolder address of the initial DEPOSITOR_WHITELIST_ROLE holder * @param isDepositLimitSetRoleHolder address of the initial IS_DEPOSIT_LIMIT_SET_ROLE holder * @param depositLimitSetRoleHolder address of the initial DEPOSIT_LIMIT_SET_ROLE holder */ struct InitParams { address collateral; address burner; uint48 epochDuration; bool depositWhitelist; bool isDepositLimit; uint256 depositLimit; address defaultAdminRoleHolder; address depositWhitelistSetRoleHolder; address depositorWhitelistRoleHolder; address isDepositLimitSetRoleHolder; address depositLimitSetRoleHolder; } /** * @notice Hints for an active balance. * @param activeSharesOfHint hint for the active shares of checkpoint * @param activeStakeHint hint for the active stake checkpoint * @param activeSharesHint hint for the active shares checkpoint */ struct ActiveBalanceOfHints { bytes activeSharesOfHint; bytes activeStakeHint; bytes activeSharesHint; } /** * @notice Emitted when a deposit is made. * @param depositor account that made the deposit * @param onBehalfOf account the deposit was made on behalf of * @param amount amount of the collateral deposited * @param shares amount of the active shares minted */ event Deposit(address indexed depositor, address indexed onBehalfOf, uint256 amount, uint256 shares); /** * @notice Emitted when a withdrawal is made. * @param withdrawer account that made the withdrawal * @param claimer account that needs to claim the withdrawal * @param amount amount of the collateral withdrawn * @param burnedShares amount of the active shares burned * @param mintedShares amount of the epoch withdrawal shares minted */ event Withdraw( address indexed withdrawer, address indexed claimer, uint256 amount, uint256 burnedShares, uint256 mintedShares ); /** * @notice Emitted when a redemption is made. * @param redeemer account that redeemed * @param claimer account that needs to claim the withdrawal * @param shares amount of the active shares burned * @param withdrawnAssets amount of the collateral withdrawn * @param mintedShares amount of the epoch withdrawal shares minted */ event Redeem( address indexed redeemer, address indexed claimer, uint256 shares, uint256 withdrawnAssets, uint256 mintedShares ); /** * @notice Emitted when a claim is made. * @param claimer account that claimed * @param recipient account that received the collateral * @param epoch epoch the collateral was claimed for * @param amount amount of the collateral claimed */ event Claim(address indexed claimer, address indexed recipient, uint256 epoch, uint256 amount); /** * @notice Emitted when a batch claim is made. * @param claimer account that claimed * @param recipient account that received the collateral * @param epochs epochs the collateral was claimed for * @param amount amount of the collateral claimed */ event ClaimBatch(address indexed claimer, address indexed recipient, uint256[] epochs, uint256 amount); /** * @notice Emitted when a slash happened. * @param slasher address of the slasher * @param slashedAmount amount of the collateral slashed */ event OnSlash(address indexed slasher, uint256 slashedAmount); /** * @notice Emitted when a deposit whitelist status is enabled/disabled. * @param status if enabled deposit whitelist */ event SetDepositWhitelist(bool status); /** * @notice Emitted when a depositor whitelist status is set. * @param account account for which the whitelist status is set * @param status if whitelisted the account */ event SetDepositorWhitelistStatus(address indexed account, bool status); /** * @notice Emitted when a deposit limit status is enabled/disabled. * @param status if enabled deposit limit */ event SetIsDepositLimit(bool status); /** * @notice Emitted when a deposit limit is set. * @param limit deposit limit (maximum amount of the collateral that can be in the vault simultaneously) */ event SetDepositLimit(uint256 limit); /** * @notice Emitted when a delegator is set. * @param delegator vault's delegator to delegate the stake to networks and operators * @dev Can be set only once. */ event SetDelegator(address indexed delegator); /** * @notice Emitted when a slasher is set. * @param slasher vault's slasher to provide a slashing mechanism to networks * @dev Can be set only once. */ event SetSlasher(address indexed slasher); /** * @notice Check if the vault is fully initialized (a delegator and a slasher are set). * @return if the vault is fully initialized */ function isInitialized() external view returns (bool); /** * @notice Get a total amount of the collateral that can be slashed. * @return total amount of the slashable collateral */ function totalStake() external view returns (uint256); /** * @notice Get an active balance for a particular account at a given timestamp using hints. * @param account account to get the active balance for * @param timestamp time point to get the active balance for the account at * @param hints hints for checkpoints' indexes * @return active balance for the account at the timestamp */ function activeBalanceOfAt( address account, uint48 timestamp, bytes calldata hints ) external view returns (uint256); /** * @notice Get an active balance for a particular account. * @param account account to get the active balance for * @return active balance for the account */ function activeBalanceOf( address account ) external view returns (uint256); /** * @notice Get withdrawals for a particular account at a given epoch (zero if claimed). * @param epoch epoch to get the withdrawals for the account at * @param account account to get the withdrawals for * @return withdrawals for the account at the epoch */ function withdrawalsOf(uint256 epoch, address account) external view returns (uint256); /** * @notice Get a total amount of the collateral that can be slashed for a given account. * @return total amount of the slashable collateral */ function slashableBalanceOf( address account ) external view returns (uint256); /** * @notice Deposit collateral into the vault. * @param onBehalfOf account the deposit is made on behalf of * @param amount amount of the collateral to deposit * @return depositedAmount amount of the collateral deposited * @return mintedShares amount of the active shares minted */ function deposit( address onBehalfOf, uint256 amount ) external returns (uint256 depositedAmount, uint256 mintedShares); /** * @notice Withdraw collateral from the vault (it will be claimable after the next epoch). * @param claimer account that needs to claim the withdrawal * @param amount amount of the collateral to withdraw * @return burnedShares amount of the active shares burned * @return mintedShares amount of the epoch withdrawal shares minted */ function withdraw(address claimer, uint256 amount) external returns (uint256 burnedShares, uint256 mintedShares); /** * @notice Redeem collateral from the vault (it will be claimable after the next epoch). * @param claimer account that needs to claim the withdrawal * @param shares amount of the active shares to redeem * @return withdrawnAssets amount of the collateral withdrawn * @return mintedShares amount of the epoch withdrawal shares minted */ function redeem(address claimer, uint256 shares) external returns (uint256 withdrawnAssets, uint256 mintedShares); /** * @notice Claim collateral from the vault. * @param recipient account that receives the collateral * @param epoch epoch to claim the collateral for * @return amount amount of the collateral claimed */ function claim(address recipient, uint256 epoch) external returns (uint256 amount); /** * @notice Claim collateral from the vault for multiple epochs. * @param recipient account that receives the collateral * @param epochs epochs to claim the collateral for * @return amount amount of the collateral claimed */ function claimBatch(address recipient, uint256[] calldata epochs) external returns (uint256 amount); /** * @notice Slash callback for burning collateral. * @param slashedAmount amount to slash * @param captureTimestamp time point when the stake was captured * @dev Only the slasher can call this function. */ function onSlash(uint256 slashedAmount, uint48 captureTimestamp) external; /** * @notice Enable/disable deposit whitelist. * @param status if enabling deposit whitelist * @dev Only a DEPOSIT_WHITELIST_SET_ROLE holder can call this function. */ function setDepositWhitelist( bool status ) external; /** * @notice Set a depositor whitelist status. * @param account account for which the whitelist status is set * @param status if whitelisting the account * @dev Only a DEPOSITOR_WHITELIST_ROLE holder can call this function. */ function setDepositorWhitelistStatus(address account, bool status) external; /** * @notice Enable/disable deposit limit. * @param status if enabling deposit limit * @dev Only a IS_DEPOSIT_LIMIT_SET_ROLE holder can call this function. */ function setIsDepositLimit( bool status ) external; /** * @notice Set a deposit limit. * @param limit deposit limit (maximum amount of the collateral that can be in the vault simultaneously) * @dev Only a DEPOSIT_LIMIT_SET_ROLE holder can call this function. */ function setDepositLimit( uint256 limit ) external; /** * @notice Set a delegator. * @param delegator vault's delegator to delegate the stake to networks and operators * @dev Can be set only once. */ function setDelegator( address delegator ) external; /** * @notice Set a slasher. * @param slasher vault's slasher to provide a slashing mechanism to networks * @dev Can be set only once. */ function setSlasher( address slasher ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IVaultStorage { error InvalidTimestamp(); error NoPreviousEpoch(); /** * @notice Get a deposit whitelist enabler/disabler's role. * @return identifier of the whitelist enabler/disabler role */ function DEPOSIT_WHITELIST_SET_ROLE() external view returns (bytes32); /** * @notice Get a depositor whitelist status setter's role. * @return identifier of the depositor whitelist status setter role */ function DEPOSITOR_WHITELIST_ROLE() external view returns (bytes32); /** * @notice Get a deposit limit enabler/disabler's role. * @return identifier of the deposit limit enabler/disabler role */ function IS_DEPOSIT_LIMIT_SET_ROLE() external view returns (bytes32); /** * @notice Get a deposit limit setter's role. * @return identifier of the deposit limit setter role */ function DEPOSIT_LIMIT_SET_ROLE() external view returns (bytes32); /** * @notice Get the delegator factory's address. * @return address of the delegator factory */ function DELEGATOR_FACTORY() external view returns (address); /** * @notice Get the slasher factory's address. * @return address of the slasher factory */ function SLASHER_FACTORY() external view returns (address); /** * @notice Get a vault collateral. * @return address of the underlying collateral */ function collateral() external view returns (address); /** * @dev Get a burner to issue debt to (e.g., 0xdEaD or some unwrapper contract). * @return address of the burner */ function burner() external view returns (address); /** * @notice Get a delegator (it delegates the vault's stake to networks and operators). * @return address of the delegator */ function delegator() external view returns (address); /** * @notice Get if the delegator is initialized. * @return if the delegator is initialized */ function isDelegatorInitialized() external view returns (bool); /** * @notice Get a slasher (it provides networks a slashing mechanism). * @return address of the slasher */ function slasher() external view returns (address); /** * @notice Get if the slasher is initialized. * @return if the slasher is initialized */ function isSlasherInitialized() external view returns (bool); /** * @notice Get a time point of the epoch duration set. * @return time point of the epoch duration set */ function epochDurationInit() external view returns (uint48); /** * @notice Get a duration of the vault epoch. * @return duration of the epoch */ function epochDuration() external view returns (uint48); /** * @notice Get an epoch at a given timestamp. * @param timestamp time point to get the epoch at * @return epoch at the timestamp * @dev Reverts if the timestamp is less than the start of the epoch 0. */ function epochAt( uint48 timestamp ) external view returns (uint256); /** * @notice Get a current vault epoch. * @return current epoch */ function currentEpoch() external view returns (uint256); /** * @notice Get a start of the current vault epoch. * @return start of the current epoch */ function currentEpochStart() external view returns (uint48); /** * @notice Get a start of the previous vault epoch. * @return start of the previous epoch * @dev Reverts if the current epoch is 0. */ function previousEpochStart() external view returns (uint48); /** * @notice Get a start of the next vault epoch. * @return start of the next epoch */ function nextEpochStart() external view returns (uint48); /** * @notice Get if the deposit whitelist is enabled. * @return if the deposit whitelist is enabled */ function depositWhitelist() external view returns (bool); /** * @notice Get if a given account is whitelisted as a depositor. * @param account address to check * @return if the account is whitelisted as a depositor */ function isDepositorWhitelisted( address account ) external view returns (bool); /** * @notice Get if the deposit limit is set. * @return if the deposit limit is set */ function isDepositLimit() external view returns (bool); /** * @notice Get a deposit limit (maximum amount of the collateral that can be in the vault simultaneously). * @return deposit limit */ function depositLimit() external view returns (uint256); /** * @notice Get a total number of active shares in the vault at a given timestamp using a hint. * @param timestamp time point to get the total number of active shares at * @param hint hint for the checkpoint index * @return total number of active shares at the timestamp */ function activeSharesAt(uint48 timestamp, bytes memory hint) external view returns (uint256); /** * @notice Get a total number of active shares in the vault. * @return total number of active shares */ function activeShares() external view returns (uint256); /** * @notice Get a total amount of active stake in the vault at a given timestamp using a hint. * @param timestamp time point to get the total active stake at * @param hint hint for the checkpoint index * @return total amount of active stake at the timestamp */ function activeStakeAt(uint48 timestamp, bytes memory hint) external view returns (uint256); /** * @notice Get a total amount of active stake in the vault. * @return total amount of active stake */ function activeStake() external view returns (uint256); /** * @notice Get a total number of active shares for a particular account at a given timestamp using a hint. * @param account account to get the number of active shares for * @param timestamp time point to get the number of active shares for the account at * @param hint hint for the checkpoint index * @return number of active shares for the account at the timestamp */ function activeSharesOfAt(address account, uint48 timestamp, bytes memory hint) external view returns (uint256); /** * @notice Get a number of active shares for a particular account. * @param account account to get the number of active shares for * @return number of active shares for the account */ function activeSharesOf( address account ) external view returns (uint256); /** * @notice Get a total amount of the withdrawals at a given epoch. * @param epoch epoch to get the total amount of the withdrawals at * @return total amount of the withdrawals at the epoch */ function withdrawals( uint256 epoch ) external view returns (uint256); /** * @notice Get a total number of withdrawal shares at a given epoch. * @param epoch epoch to get the total number of withdrawal shares at * @return total number of withdrawal shares at the epoch */ function withdrawalShares( uint256 epoch ) external view returns (uint256); /** * @notice Get a number of withdrawal shares for a particular account at a given epoch (zero if claimed). * @param epoch epoch to get the number of withdrawal shares for the account at * @param account account to get the number of withdrawal shares for * @return number of withdrawal shares for the account at the epoch */ function withdrawalSharesOf(uint256 epoch, address account) external view returns (uint256); /** * @notice Get if the withdrawals are claimed for a particular account at a given epoch. * @param epoch epoch to check the withdrawals for the account at * @param account account to check the withdrawals for * @return if the withdrawals are claimed for the account at the epoch */ function isWithdrawalsClaimed(uint256 epoch, address account) external view returns (bool); }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 4096 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidDeadline","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NotNetwork","type":"error"},{"inputs":[],"name":"NotOperator","type":"error"},{"inputs":[],"name":"NotSignedByNetwork","type":"error"},{"inputs":[],"name":"NotWhitelistedEndpoint","type":"error"},{"inputs":[],"name":"OperatorAlreadyBlacklisted","type":"error"},{"inputs":[],"name":"OperatorAlreadyDisabled","type":"error"},{"inputs":[],"name":"OperatorAlreadyEnabled","type":"error"},{"inputs":[],"name":"OperatorAlreadyRegistred","type":"error"},{"inputs":[],"name":"OperatorIsBlacklisted","type":"error"},{"inputs":[],"name":"OperatorNotOptedIn","type":"error"},{"inputs":[],"name":"OperatorNotRegistred","type":"error"},{"inputs":[],"name":"OperatorVaultAlreadySetted","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"SlashingWindowTooShort","type":"error"},{"inputs":[],"name":"TooBigSlashAmount","type":"error"},{"inputs":[],"name":"UnknownSlasherType","type":"error"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"vault","type":"address"}],"name":"OperatorAndVaultSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"bool","name":"blacklist","type":"bool"}],"name":"OperatorBlacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"bool","name":"enable","type":"bool"}],"name":"OperatorEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"COLLATERAL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NETWORK","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_NET_OPTIN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_VAULT_OPTIN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLASH_PERCENT_MAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_CONFIGURATOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_EPOCH_DURATION","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_VERSION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"blacklist","type":"bool"}],"name":"blacklistOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultVaultParams","outputs":[{"components":[{"internalType":"bool","name":"depositWhitelist","type":"bool"},{"internalType":"bool","name":"isDepositLimit","type":"bool"},{"internalType":"uint256","name":"depositLimit","type":"uint256"},{"internalType":"address","name":"burner","type":"address"},{"internalType":"address","name":"depositWhitelistSetRoleHolder","type":"address"},{"internalType":"address","name":"depositorWhitelistRoleHolder","type":"address"},{"internalType":"address","name":"isDepositLimitSetRoleHolder","type":"address"},{"internalType":"address","name":"depositLimitSetRoleHolder","type":"address"}],"internalType":"struct HinkalMiddleware.VaultInitParams","name":"vaultInitParams","type":"tuple"},{"components":[{"internalType":"uint64","name":"slasherIndex","type":"uint64"},{"internalType":"uint48","name":"vetoDuration","type":"uint48"},{"internalType":"uint256","name":"resolverSetEpochsDelay","type":"uint256"}],"internalType":"struct HinkalMiddleware.SlasherInitParams","name":"slasherInitParams","type":"tuple"},{"components":[{"internalType":"uint64","name":"delegatorIndex","type":"uint64"},{"internalType":"address","name":"hookSetRoleHolder","type":"address"},{"internalType":"address","name":"hook","type":"address"}],"internalType":"struct HinkalMiddleware.DelegatorInitParams","name":"delegatorInitParams","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"endpoint","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint48","name":"deadline","type":"uint48"},{"internalType":"bytes","name":"paylod","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getOperatorStake","outputs":[{"internalType":"uint256","name":"stake","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hinkalHelper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_network","type":"address"},{"internalType":"address","name":"_operatorRegistry","type":"address"},{"internalType":"address","name":"_operatorNetOptin","type":"address"},{"internalType":"address","name":"_operatorVaultOptin","type":"address"},{"internalType":"address","name":"_vaultConfigurator","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"address","name":"_hinkalHelper","type":"address"},{"internalType":"uint48","name":"_vaultEpochDuration","type":"uint48"},{"internalType":"uint256","name":"_minimumStake","type":"uint256"},{"internalType":"uint256","name":"_slashPercent","type":"uint256"},{"components":[{"components":[{"internalType":"bool","name":"depositWhitelist","type":"bool"},{"internalType":"bool","name":"isDepositLimit","type":"bool"},{"internalType":"uint256","name":"depositLimit","type":"uint256"},{"internalType":"address","name":"burner","type":"address"},{"internalType":"address","name":"depositWhitelistSetRoleHolder","type":"address"},{"internalType":"address","name":"depositorWhitelistRoleHolder","type":"address"},{"internalType":"address","name":"isDepositLimitSetRoleHolder","type":"address"},{"internalType":"address","name":"depositLimitSetRoleHolder","type":"address"}],"internalType":"struct HinkalMiddleware.VaultInitParams","name":"vaultInitParams","type":"tuple"},{"components":[{"internalType":"uint64","name":"slasherIndex","type":"uint64"},{"internalType":"uint48","name":"vetoDuration","type":"uint48"},{"internalType":"uint256","name":"resolverSetEpochsDelay","type":"uint256"}],"internalType":"struct HinkalMiddleware.SlasherInitParams","name":"slasherInitParams","type":"tuple"},{"components":[{"internalType":"uint64","name":"delegatorIndex","type":"uint64"},{"internalType":"address","name":"hookSetRoleHolder","type":"address"},{"internalType":"address","name":"hook","type":"address"}],"internalType":"struct HinkalMiddleware.DelegatorInitParams","name":"delegatorInitParams","type":"tuple"}],"internalType":"struct HinkalMiddleware.AddOperatorAndVaultParams","name":"_defaultVaultParams","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isValidOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isWhitelistedEndpoint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nonces","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"operatorInfos","outputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"bool","name":"isBlacklisted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"registerOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"relayer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newHinkalHelper","type":"address"}],"name":"setHinkalHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"setOperatorState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"endpoint","type":"address"},{"internalType":"bool","name":"val","type":"bool"}],"name":"setWhitelistedEndpoint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"slash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"slashAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slashPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080806040523460d2577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c1660c1576002600160401b03196001600160401b03821601605c575b60405161389f90816100d88239f35b6001600160401b0319166001600160401b039081177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a13880604d565b63f92ee8a960e01b60005260046000fd5b600080fdfe60a0604052600436101561001b575b361561001957600080fd5b005b60006080526080513560e01c8062ff0794146125965780630da7d04314612555578063141a468c1461252257806318b01c1f146124fa57806324bbab8b146124d25780632ce30d2914611a5f5780633682a4501461130e5780633abd53ca146112cb5780634d34d5ce146112835780636343b15f146112645780636d5149c014611204578063715018a61461116057806373849eb014610d9757806383ce032214610d6f5780638406c07914610d4757806384b0196e14610bb55780638759e6d114610b8c5780638da5cb5b14610b45578063911e928d146105c757806393fe38891461059f5780639671084a14610577578063a73f4dac14610393578063b25bc0c01461036b578063c96be4cb146102fb578063cc11e0be146102d1578063e2d53d7c146102a4578063e4e88de814610279578063ec14c5e514610214578063ec5ffac2146101f5578063f2fde38b146101c6578063f4595b89146101a95763fefdc6c40361000e57346101a3576080516003193601126101a35760206040516127108152f35b60805180fd5b346101a3576080516003193601126101a357602060405160018152f35b346101a35760206003193601126101a3576101ef6101e2612724565b6101ea612c63565b612ba4565b60805180f35b346101a3576080516003193601126101a3576020600854604051908152f35b346101a35760406003193601126101a35761022d612724565b6001600160a01b036080515416330361024d576101ef9060243590612eca565b7f8f54ee5c00000000000000000000000000000000000000000000000000000000608051526004608051fd5b346101a35760206003193601126101a357602061029c610297612724565b612a73565b604051908152f35b346101a35760206003193601126101a35760206102c76102c2612724565b6128fc565b6040519015158152f35b346101a3576080516003193601126101a357602065ffffffffffff60045460a01c16604051908152f35b346101a35760206003193601126101a357610314612724565b6001600160a01b036080515416330361024d5761033081612a73565b9060095491828102928184041490151715610353576127106101ef920490612eca565b634e487b7160e01b6080515260116004526024608051fd5b346101a3576080516003193601126101a35760206001600160a01b0360045416604051908152f35b346101a3576080516003193601126101a3576040516103b1816127a0565b600d549060ff821615158152602081019160081c60ff1615158252600e5460408201908152600f546001600160a01b0316606083019081526010546001600160a01b0316608084019081526011546001600160a01b031660a085019081526012546001600160a01b031660c086019081526013546001600160a01b031660e08701908152604051916104428361276e565b6014549367ffffffffffffffff85168452602084019460401c65ffffffffffff16855260155495604085019687526040519761047d8961276e565b6016549967ffffffffffffffff8b168a5260208a019a60401c6001600160a01b03168b526017546001600160a01b03169b60408b019c8d526040519d8e91511515825251151590602001525160408d0152516001600160a01b031660608c0152516001600160a01b031660808b0152516001600160a01b031660a08a0152516001600160a01b031660c0890152516001600160a01b031660e08801525167ffffffffffffffff166101008701525165ffffffffffff16610120860152516101408501525167ffffffffffffffff16610160840152516001600160a01b0316610180830152516001600160a01b03166101a08201526101c090f35b346101a3576080516003193601126101a35760206001600160a01b0360075416604051908152f35b346101a3576080516003193601126101a35760206001600160a01b0360025416604051908152f35b346101a35760206003193601126101a3576105e0612724565b6001600160a01b0381168060805152600c6020526040608051209161061282600052600b602052604060002054151590565b15610b1957825460ff8160a81c16610aed576003546040517f220d32d40000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529283166024820181905292909160209183916044918391165afa9081156108745760805191610abe575b5015610a9257602060049160405192838092630ce9b79360e41b82525afa9081156108745760805191610a50575b50608051546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156108745760805191610a1e575b50600854116108c15761073f81613694565b50600460206001600160a01b0384541660405192838092630ce9b79360e41b82525afa80156108745760805190610881575b6080515460601b6bffffffffffffffffffffffff191691506001600160a01b0316803b156101a357604051917f020cf0c2000000000000000000000000000000000000000000000000000000008352600483015282602483015260001960448301528160648160805193608051905af180156108745761085b575b5081740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff60019454161790557fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f1608051608051a360805180f35b608051610867916127bd565b6080516101a357826107ec565b6040513d608051823e3d90fd5b506020813d6020116108b9575b8161089b602093836127bd565b810103126101a3576108b46001600160a01b03916128d9565b610771565b3d915061088e565b906108cb8261339f565b50600460206001600160a01b0383541660405192838092630ce9b79360e41b82525afa801561087457608051906109de575b6080515460601b6bffffffffffffffffffffffff191691506001600160a01b0316803b156101a357604051917f020cf0c2000000000000000000000000000000000000000000000000000000008352600483015283602483015260805160448301528160648160805193608051905af18015610874576109cc575b5080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055608051907fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18280a36101ef565b6080516109d8916127bd565b82610978565b506020813d602011610a16575b816109f8602093836127bd565b810103126101a357610a116001600160a01b03916128d9565b6108fd565b3d91506109eb565b90506020813d602011610a48575b81610a39602093836127bd565b810103126101a357518361072d565b3d9150610a2c565b90506020813d602011610a8a575b81610a6b602093836127bd565b810103126101a35761071891610a826020926128d9565b9150916106b5565b3d9150610a5e565b7f9a39813e00000000000000000000000000000000000000000000000000000000608051526004608051fd5b610ae0915060203d602011610ae6575b610ad881836127bd565b810190612884565b85610687565b503d610ace565b7f23daf16a00000000000000000000000000000000000000000000000000000000608051526004608051fd5b7f7c214f0400000000000000000000000000000000000000000000000000000000608051526004608051fd5b346101a3576080516003193601126101a35760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101a3576080516003193601126101a35760206001600160a01b036080515416604051908152f35b346101a3576080516003193601126101a3577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100541580610d1e575b15610cc057610c60610c00612cfe565b610c08612df5565b60405190602090610c6e90610c1d83856127bd565b608080518552513681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e0870190612843565b908582036040870152612843565b46606085015230608085015260805160a085015283810360c08501528180845192838152019301916080515b828110610ca957505050500390f35b835185528695509381019392810192600101610c9a565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015415610bf0565b346101a3576080516003193601126101a35760206001600160a01b0360065416604051908152f35b346101a3576080516003193601126101a35760206001600160a01b0360015416604051908152f35b60a06003193601126101a357610dab612724565b6024359060443565ffffffffffff811691908290036101a35760643567ffffffffffffffff81116101a357610de49036906004016127fc565b9160843567ffffffffffffffff81116101a357610e059036906004016127fc565b602460206001600160a01b0360075416604051928380927f946b30ef0000000000000000000000000000000000000000000000000000000082523260048301525afa9081156108745760805191611141575b508015611132575b156101a357326001600160a01b03196006541617600655604051916042602084013281526001600160a01b0386169485604082015288606082015283608082015260a080820152610ec581610eb760c082018b612843565b03601f1981018352826127bd565b519020610ed06137ba565b610ed8613824565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a08152610f2960c0826127bd565b51902090604051917f190100000000000000000000000000000000000000000000000000000000000083526002830152602282015220908660805152601960205260ff60406080512054166111065765ffffffffffff421611156110da57610f9d91610f94916134f5565b90929192613531565b6001600160a01b038060805154169116036110ae5760805152601860205260ff604060805120541615611082573447106110525760805182516110149382919060200134855af13d1561104a573d91610ff5836127e0565b9261100360405194856127bd565b83526080513d90602085013e613604565b50608051526019602052604060805120600160ff1982541617905560016001600160a01b03196006541617600655608051608051f35b606091613604565b7fcd7860590000000000000000000000000000000000000000000000000000000060805152306004526024608051fd5b7f8ee6bc3100000000000000000000000000000000000000000000000000000000608051526004608051fd5b7fd2bac4ba00000000000000000000000000000000000000000000000000000000608051526004608051fd5b7f769d11e400000000000000000000000000000000000000000000000000000000608051526004608051fd5b7f756688fe00000000000000000000000000000000000000000000000000000000608051526004608051fd5b5061113c326128fc565b610e5f565b61115a915060203d602011610ae657610ad881836127bd565b86610e57565b346101a3576080516003193601126101a35761117a612c63565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300556001600160a01b0360805191167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0608051608051a360805180f35b346101a35760206003193601126101a3576001600160a01b03611225612724565b1660805152600c60205260606040608051205460ff604051916001600160a01b0381168352818160a01c161515602084015260a81c1615156040820152f35b346101a3576080516003193601126101a3576020600954604051908152f35b346101a3576001600160a01b036112993661273f565b91906112a3612c63565b166080515260186020526040608051209060ff60ff1983541691151516179055608051608051f35b346101a35760206003193601126101a3576001600160a01b036112ec612724565b6112f4612c63565b166001600160a01b03196007541617600755608051608051f35b346101a35760206003193601126101a357611327612724565b61132f612c63565b6001600160a01b038116908160805152600c6020526001600160a01b036040608051205416611a335761136f82600052600b602052604060002054151590565b611a0757602460206001600160a01b0360015416604051928380927f14887c580000000000000000000000000000000000000000000000000000000082528760048301525afa90811561087457608051916119e8575b5015610b1957600254608051546040517f220d32d40000000000000000000000000000000000000000000000000000000081526001600160a01b03938416600482015290831660248201529160209183916044918391165afa90811561087457608051916119c9575b5015610a92576001600160a01b0360055416906001600160a01b03600f541691600454600d54600e546001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416936001600160a01b03601054166001600160a01b0360115416916001600160a01b0360125416936001600160a01b03601354169560405192610160840184811067ffffffffffffffff82111761199957604052808452602084019b8c52604084018960a01c65ffffffffffff168152606085019160ff841615158352608086019360081c60ff161515845260a0860194855260c08601958c875260e0810197885261010081019889526101208101998a5261014001998a526040519d8e916020830152516001600160a01b031690604001525165ffffffffffff1660608d015251151560808c015251151560a08b01525160c08a0152516001600160a01b031660e0890152516001600160a01b0316610100880152516001600160a01b0316610120870152516001600160a01b0316610140860152516001600160a01b031661016085015261016084526115d8610180856127bd565b60405160609490916115ea86846127bd565b6002835260208301601f1987013682378351156119b1573090528251600110156119b157838360409586899601526116f06001600160a01b03601754166116e26016549389519261163a8461276e565b86845260208401526001600160a01b03858b1c168a84015289519261165e8461276e565b83526116b1602084018281528b85019283526001600160a01b038c519c8d966020808901525182815116828901528d836020830151169089015201511660808601525160a08086015260e085019061289c565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030160c085015261289c565b03601f1981018852876127bd565b60145467ffffffffffffffff811691908261193e57506040516117146020826127bd565b608051815260003660208301375b6040519261172f846127a0565b6001845260208401948552604084019687528784019267ffffffffffffffff1683526080840198895260a08401926001845260c0850191825260e08501928352604051998a98899788977fc48927e400000000000000000000000000000000000000000000000000000000895260048901602090525167ffffffffffffffff166024890152516001600160a01b031660448801525160648701610100905261012487016117db91612843565b915167ffffffffffffffff16608487015251908581037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc0160a487015261182191612843565b9251151560c48501525167ffffffffffffffff1660e484015251908281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc0161010484015261187091612843565b0391608051906001600160a01b03165af192831561087457608051936118ec575b50508060805152600c6020526001600160a01b03604060805120921691826001600160a01b03198254161790557f7f74cf9c79e65b11e373ad23da18f4a761fe28401a5a663bbd34ffc2633f5bab608051608051a360805180f35b9080929350813d8311611937575b61190481836127bd565b810103126101a35761192e604061191a836128d9565b92611927602082016128d9565b50016128d9565b50908280611891565b503d6118fa565b60155460408051985091821c65ffffffffffff1691880167ffffffffffffffff811189821017611999578b98602091604052838152019081526040519160208301525160408201526040815261199487826127bd565b611722565b634e487b7160e01b6080515260416004526024608051fd5b634e487b7160e01b6080515260326004526024608051fd5b6119e2915060203d602011610ae657610ad881836127bd565b8261142e565b611a01915060203d602011610ae657610ad881836127bd565b836113c5565b7f7dc7d19c00000000000000000000000000000000000000000000000000000000608051526004608051fd5b7f6b090a6200000000000000000000000000000000000000000000000000000000608051526004608051fd5b346101a3576103006003193601126101a357611a79612724565b6024356001600160a01b038116908190036101a3576044356001600160a01b03811691908290036101a3576064356001600160a01b038116908190036101a3576084356001600160a01b03811693908490036101a35760a4356001600160a01b03811694908590036101a35760c4356001600160a01b03811694908590036101a35760e4359065ffffffffffff821682036101a3576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebc3601126101a3577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549667ffffffffffffffff8816801590816124c2575b60011490816124b8575b1590816124af575b5061248357600167ffffffffffffffff198916177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005560ff8860401c161561242e575b611bcd61349c565b611bd561349c565b611bde33612ba4565b60408051909990611bef8b826127bd565b601081527f48696e6b616c4d6964646c65776172650000000000000000000000000000000060208201528a5190611c268c836127bd565b600182527f31000000000000000000000000000000000000000000000000000000000000006020830152611c5861349c565b80519067ffffffffffffffff8211611999578190611c967fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10254612cc4565b601f81116123b8575b506020906001601f8411146123125760805192612307575b50506000198260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102555b80519067ffffffffffffffff821161199957611d277fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10354612cc4565b601f811161229c575b506020906001601f8411146121e9579180916001600160a01b039493608051926121de575b50506000198260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103555b6080517fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100556080517fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10155166001600160a01b0319608051541617608051556001600160a01b031960055416176005556001600160a01b031960015416176001557fffffffffffff000000000000000000000000000000000000000000000000000079ffffffffffff00000000000000000000000000000000000000006004549260a01b16911617176004556001600160a01b031960025416176002556001600160a01b0319600354161760035561010435600855610124356009556001600160a01b031960075416176007556080515061014435801515908181036101a3575060ff60ff19600d5416911617600d556080515061016435801515908181036101a357507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff61ff00600d549260081b16911617600d5561018435600e55608051506101a4356001600160a01b038116908181036101a357506001600160a01b0319600f541617600f55608051506101c4356001600160a01b038116908181036101a357506001600160a01b03196010541617601055608051506101e4356001600160a01b038116908181036101a357506001600160a01b0319601154161760115560805150610204356001600160a01b038116908181036101a357506001600160a01b0319601254161760125560805150610224356001600160a01b038116908181036101a357506001600160a01b03196013541617601355608051506102443567ffffffffffffffff8116908181036101a3575067ffffffffffffffff1960145416176014556102643565ffffffffffff811681036101a3577fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff6dffffffffffff000000000000000060145492851b1691161760145561028435601555608051506102a43567ffffffffffffffff8116908181036101a3575067ffffffffffffffff196016541617601655608051506102c4356001600160a01b03811681036101a3577fffffffff0000000000000000000000000000000000000000ffffffffffffffff7bffffffffffffffffffffffffffffffffffffffff000000000000000060165492851b16911617601655608051506102e435906001600160a01b0382168083036101a35760ff92506001600160a01b0319601754161760175560016001600160a01b0319600654161760065560401c16156121485760805180f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2917fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555160018152a1806101ef565b015190508d80611d55565b90601f198316917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103608051528160805120926080515b81811061228457509160019391856001600160a01b039796941061226b575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10355611d89565b015160001960f88460031b161c191690558d808061223e565b9293602060018192878601518155019501930161221f565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10360805152602060805120601f840160051c810191602085106122fd575b601f0160051c01905b8181106122f05750611d30565b60805181556001016122e3565b90915081906122da565b015190508d80611cb7565b608080517fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10290525182812093601f1916905b8181106123a05750908460019594939210612387575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10255611ceb565b015160001960f88460031b161c191690558d808061235a565b92936020600181928786015181550195019301612344565b9091507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10260805152602060805120601f840160051c81019160208510612424575b90601f859493920160051c01905b8181106124145750611c9f565b6080518155849350600101612407565b90915081906123f9565b680100000000000000017fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000008916177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055611bc5565b7ff92ee8a900000000000000000000000000000000000000000000000000000000608051526004608051fd5b9050158a611b82565b303b159150611b7a565b60408a901c60ff16159150611b70565b346101a3576080516003193601126101a35760206001600160a01b0360055416604051908152f35b346101a3576080516003193601126101a35760206001600160a01b0360035416604051908152f35b346101a35760206003193601126101a357600435608051526019602052602060ff60406080512054166040519015158152f35b346101a35760206003193601126101a3576001600160a01b03612576612724565b16608051526018602052602060ff60406080512054166040519015158152f35b346101a3576001600160a01b036125ac3661273f565b91906125b6612c63565b16908160805152600c602052604060805120816000146126c157805460ff8160a81c16612695577fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790556000828152600b602052604090205461265e575b1515907f064709432483b7469e36cc282db9aa95ee5df7d163c25983d72758f36d89227a608051608051a360805180f35b6126678261339f565b50608051827fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18280a361262d565b7f1996476b00000000000000000000000000000000000000000000000000000000608051526004608051fd5b805460ff8160a81c16156126f8577fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16905561262d565b7ff4ef2b3f00000000000000000000000000000000000000000000000000000000608051526004608051fd5b600435906001600160a01b038216820361273a57565b600080fd5b600319604091011261273a576004356001600160a01b038116810361273a5790602435801515810361273a5790565b6060810190811067ffffffffffffffff82111761278a57604052565b634e487b7160e01b600052604160045260246000fd5b610100810190811067ffffffffffffffff82111761278a57604052565b90601f601f19910116810190811067ffffffffffffffff82111761278a57604052565b67ffffffffffffffff811161278a57601f01601f191660200190565b81601f8201121561273a57803590612813826127e0565b9261282160405194856127bd565b8284526020838301011161273a57816000926020809301838601378301015290565b919082519283825260005b84811061286f575050601f19601f8460006020809697860101520116010190565b8060208092840101518282860101520161284e565b9081602091031261273a5751801515810361273a5790565b906020808351928381520192019060005b8181106128ba5750505090565b82516001600160a01b03168452602093840193909201916001016128ad565b51906001600160a01b038216820361273a57565b9081602091031261273a575190565b6001600160a01b038116600052600c6020526001600160a01b03604060002054168015612a4957602060049160405192838092630ce9b79360e41b82525afa9081156129fb57600091612a07575b506000546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156129fb576000916129c9575b50600854111590565b90506020813d6020116129f3575b816129e4602093836127bd565b8101031261273a5751386129c0565b3d91506129d7565b6040513d6000823e3d90fd5b90506020813d602011612a41575b81612a22602093836127bd565b8101031261273a576129ac91612a396020926128d9565b91509161294a565b3d9150612a15565b7fae2411a60000000000000000000000000000000000000000000000000000000060005260046000fd5b6001600160a01b038116600052600c602052600460206001600160a01b036040600020541660405192838092630ce9b79360e41b82525afa9081156129fb57600091612b62575b506000546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156129fb57600091612b33575090565b90506020813d602011612b5a575b81612b4e602093836127bd565b8101031261273a575190565b3d9150612b41565b90506020813d602011612b9c575b81612b7d602093836127bd565b8101031261273a57612b1c91612b946020926128d9565b915091612aba565b3d9150612b70565b6001600160a01b03168015612c34576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b7f1e4fbdf700000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303612c9657565b7f118cdaa7000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b90600182811c92168015612cf4575b6020831014612cde57565b634e487b7160e01b600052602260045260246000fd5b91607f1691612cd3565b604051906000827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025491612d3183612cc4565b8083529260018116908115612dd65750600114612d57575b612d55925003836127bd565b565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102600090815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b818310612dba575050906020612d5592820101612d49565b6020919350806001915483858901015201910190918492612da2565b60209250612d5594915060ff191682840152151560051b820101612d49565b604051906000827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035491612e2883612cc4565b8083529260018116908115612dd65750600114612e4b57612d55925003836127bd565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103600090815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b818310612eae575050906020612d5592820101612d49565b6020919350806001915483858901015201910190918492612e96565b9190612ed583612a73565b92818410613347576000936001600160a01b03821692838652600c6020526001600160a01b036040872054169265ffffffffffff4216906bffffffffffffffffffffffff1980895460601b1616906040517fb13442710000000000000000000000000000000000000000000000000000000081526020816004818a5afa801561333c578a906132f8575b6001600160a01b03915016906040517fbb24fe8a000000000000000000000000000000000000000000000000000000008152602081600481865afa80156132ed578b9061329e575b67ffffffffffffffff9150166002811015613276579185918b959493156000146131ea576020958694613023604051612fe088826127bd565b838152601f1988013689830137604051988997889687957f021a8156000000000000000000000000000000000000000000000000000000008752600487016136f4565b03925af180156131df576131b1575b50505b810390811161319d576008541161304d575b50509050565b60046020859261305c8561339f565b5060405192838092630ce9b79360e41b82525afa801561319257829061314e575b825460601b6bffffffffffffffffffffffff191691506001600160a01b0316803b1561314a576064839260405197889384927f020cf0c200000000000000000000000000000000000000000000000000000000845260048401528760248401528160448401525af193841561313d576040939461312d575b50908152600c602052207fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8154169055803880613047565b81613137916127bd565b386130f5565b50604051903d90823e3d90fd5b8280fd5b506020813d60201161318a575b81613168602093836127bd565b81010312613186576131816001600160a01b03916128d9565b61307d565b5080fd5b3d915061315b565b6040513d84823e3d90fd5b602485634e487b7160e01b81526011600452fd5b816131d092903d106131d8575b6131c881836127bd565b8101906128ed565b503880613032565b503d6131be565b6040513d8a823e3d90fd5b60209586946132426040516131ff88826127bd565b838152601f1988013689830137604051988997889687957f545ce389000000000000000000000000000000000000000000000000000000008752600487016136f4565b03925af180156131df57613258575b5050613035565b8161326e92903d106131d8576131c881836127bd565b503880613251565b60048b7fa739d4e2000000000000000000000000000000000000000000000000000000008152fd5b506020813d6020116132e5575b816132b8602093836127bd565b810103126132e1575167ffffffffffffffff811681036132e15767ffffffffffffffff90612fa7565b8a80fd5b3d91506132ab565b6040513d8d823e3d90fd5b506020813d602011613334575b81613312602093836127bd565b810103126133305761332b6001600160a01b03916128d9565b612f5f565b8980fd5b3d9150613305565b6040513d8c823e3d90fd5b7f8cc309fd0000000000000000000000000000000000000000000000000000000060005260046000fd5b80548210156133895760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b6000818152600b6020526040902054801561349557600019810181811161347f57600a5490600019820191821161347f5781810361342e575b505050600a54801561341857600019016133f381600a613371565b60001982549160031b1b19169055600a55600052600b60205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61346761343f61345093600a613371565b90549060031b1c928392600a613371565b81939154906000199060031b92831b921b19161790565b9055600052600b6020526040600020553880806133d8565b634e487b7160e01b600052601160045260246000fd5b5050600090565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c16156134cb57565b7fd7e6bcf80000000000000000000000000000000000000000000000000000000060005260046000fd5b81519190604183036135265761351f92506020820151906060604084015193015160001a90613731565b9192909190565b505060009160029190565b91909160048110156135ee578061354757509050565b60006001820361357b577ff645eedf0000000000000000000000000000000000000000000000000000000060005260046000fd5b50600281036135b257827ffce698f70000000000000000000000000000000000000000000000000000000060005260045260246000fd5b90916003600092146135c2575050565b602492507fd78bce0c000000000000000000000000000000000000000000000000000000008252600452fd5b634e487b7160e01b600052602160045260246000fd5b90613643575080511561361957805190602001fd5b7f1425ea420000000000000000000000000000000000000000000000000000000060005260046000fd5b8151158061368b575b613654575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b50803b1561364c565b80600052600b602052604060002054156000146136ee57600a546801000000000000000081101561278a576136d5613450826001859401600a55600a613371565b9055600a5490600052600b602052604060002055600190565b50600090565b919360a0936001600160a01b0361372e979665ffffffffffff94865216602085015260408401521660608201528160808201520190612843565b90565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116137ae579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa156129fb576000516001600160a01b038116156137a25790600090600090565b50600090600190600090565b50505060009160039190565b6137c2612cfe565b80519081156137d2576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1005480156137ff5790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b61382c612df5565b805190811561383c576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015480156137ff579056fea26469706673582212202425e882d09aad0060af28551240162671c467ba9c0c881999ef30eb50c6e21864736f6c634300081b0033
Deployed Bytecode
0x60a0604052600436101561001b575b361561001957600080fd5b005b60006080526080513560e01c8062ff0794146125965780630da7d04314612555578063141a468c1461252257806318b01c1f146124fa57806324bbab8b146124d25780632ce30d2914611a5f5780633682a4501461130e5780633abd53ca146112cb5780634d34d5ce146112835780636343b15f146112645780636d5149c014611204578063715018a61461116057806373849eb014610d9757806383ce032214610d6f5780638406c07914610d4757806384b0196e14610bb55780638759e6d114610b8c5780638da5cb5b14610b45578063911e928d146105c757806393fe38891461059f5780639671084a14610577578063a73f4dac14610393578063b25bc0c01461036b578063c96be4cb146102fb578063cc11e0be146102d1578063e2d53d7c146102a4578063e4e88de814610279578063ec14c5e514610214578063ec5ffac2146101f5578063f2fde38b146101c6578063f4595b89146101a95763fefdc6c40361000e57346101a3576080516003193601126101a35760206040516127108152f35b60805180fd5b346101a3576080516003193601126101a357602060405160018152f35b346101a35760206003193601126101a3576101ef6101e2612724565b6101ea612c63565b612ba4565b60805180f35b346101a3576080516003193601126101a3576020600854604051908152f35b346101a35760406003193601126101a35761022d612724565b6001600160a01b036080515416330361024d576101ef9060243590612eca565b7f8f54ee5c00000000000000000000000000000000000000000000000000000000608051526004608051fd5b346101a35760206003193601126101a357602061029c610297612724565b612a73565b604051908152f35b346101a35760206003193601126101a35760206102c76102c2612724565b6128fc565b6040519015158152f35b346101a3576080516003193601126101a357602065ffffffffffff60045460a01c16604051908152f35b346101a35760206003193601126101a357610314612724565b6001600160a01b036080515416330361024d5761033081612a73565b9060095491828102928184041490151715610353576127106101ef920490612eca565b634e487b7160e01b6080515260116004526024608051fd5b346101a3576080516003193601126101a35760206001600160a01b0360045416604051908152f35b346101a3576080516003193601126101a3576040516103b1816127a0565b600d549060ff821615158152602081019160081c60ff1615158252600e5460408201908152600f546001600160a01b0316606083019081526010546001600160a01b0316608084019081526011546001600160a01b031660a085019081526012546001600160a01b031660c086019081526013546001600160a01b031660e08701908152604051916104428361276e565b6014549367ffffffffffffffff85168452602084019460401c65ffffffffffff16855260155495604085019687526040519761047d8961276e565b6016549967ffffffffffffffff8b168a5260208a019a60401c6001600160a01b03168b526017546001600160a01b03169b60408b019c8d526040519d8e91511515825251151590602001525160408d0152516001600160a01b031660608c0152516001600160a01b031660808b0152516001600160a01b031660a08a0152516001600160a01b031660c0890152516001600160a01b031660e08801525167ffffffffffffffff166101008701525165ffffffffffff16610120860152516101408501525167ffffffffffffffff16610160840152516001600160a01b0316610180830152516001600160a01b03166101a08201526101c090f35b346101a3576080516003193601126101a35760206001600160a01b0360075416604051908152f35b346101a3576080516003193601126101a35760206001600160a01b0360025416604051908152f35b346101a35760206003193601126101a3576105e0612724565b6001600160a01b0381168060805152600c6020526040608051209161061282600052600b602052604060002054151590565b15610b1957825460ff8160a81c16610aed576003546040517f220d32d40000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529283166024820181905292909160209183916044918391165afa9081156108745760805191610abe575b5015610a9257602060049160405192838092630ce9b79360e41b82525afa9081156108745760805191610a50575b50608051546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156108745760805191610a1e575b50600854116108c15761073f81613694565b50600460206001600160a01b0384541660405192838092630ce9b79360e41b82525afa80156108745760805190610881575b6080515460601b6bffffffffffffffffffffffff191691506001600160a01b0316803b156101a357604051917f020cf0c2000000000000000000000000000000000000000000000000000000008352600483015282602483015260001960448301528160648160805193608051905af180156108745761085b575b5081740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff60019454161790557fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f1608051608051a360805180f35b608051610867916127bd565b6080516101a357826107ec565b6040513d608051823e3d90fd5b506020813d6020116108b9575b8161089b602093836127bd565b810103126101a3576108b46001600160a01b03916128d9565b610771565b3d915061088e565b906108cb8261339f565b50600460206001600160a01b0383541660405192838092630ce9b79360e41b82525afa801561087457608051906109de575b6080515460601b6bffffffffffffffffffffffff191691506001600160a01b0316803b156101a357604051917f020cf0c2000000000000000000000000000000000000000000000000000000008352600483015283602483015260805160448301528160648160805193608051905af18015610874576109cc575b5080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055608051907fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18280a36101ef565b6080516109d8916127bd565b82610978565b506020813d602011610a16575b816109f8602093836127bd565b810103126101a357610a116001600160a01b03916128d9565b6108fd565b3d91506109eb565b90506020813d602011610a48575b81610a39602093836127bd565b810103126101a357518361072d565b3d9150610a2c565b90506020813d602011610a8a575b81610a6b602093836127bd565b810103126101a35761071891610a826020926128d9565b9150916106b5565b3d9150610a5e565b7f9a39813e00000000000000000000000000000000000000000000000000000000608051526004608051fd5b610ae0915060203d602011610ae6575b610ad881836127bd565b810190612884565b85610687565b503d610ace565b7f23daf16a00000000000000000000000000000000000000000000000000000000608051526004608051fd5b7f7c214f0400000000000000000000000000000000000000000000000000000000608051526004608051fd5b346101a3576080516003193601126101a35760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101a3576080516003193601126101a35760206001600160a01b036080515416604051908152f35b346101a3576080516003193601126101a3577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100541580610d1e575b15610cc057610c60610c00612cfe565b610c08612df5565b60405190602090610c6e90610c1d83856127bd565b608080518552513681376040519586957f0f00000000000000000000000000000000000000000000000000000000000000875260e08588015260e0870190612843565b908582036040870152612843565b46606085015230608085015260805160a085015283810360c08501528180845192838152019301916080515b828110610ca957505050500390f35b835185528695509381019392810192600101610c9a565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015415610bf0565b346101a3576080516003193601126101a35760206001600160a01b0360065416604051908152f35b346101a3576080516003193601126101a35760206001600160a01b0360015416604051908152f35b60a06003193601126101a357610dab612724565b6024359060443565ffffffffffff811691908290036101a35760643567ffffffffffffffff81116101a357610de49036906004016127fc565b9160843567ffffffffffffffff81116101a357610e059036906004016127fc565b602460206001600160a01b0360075416604051928380927f946b30ef0000000000000000000000000000000000000000000000000000000082523260048301525afa9081156108745760805191611141575b508015611132575b156101a357326001600160a01b03196006541617600655604051916042602084013281526001600160a01b0386169485604082015288606082015283608082015260a080820152610ec581610eb760c082018b612843565b03601f1981018352826127bd565b519020610ed06137ba565b610ed8613824565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a08152610f2960c0826127bd565b51902090604051917f190100000000000000000000000000000000000000000000000000000000000083526002830152602282015220908660805152601960205260ff60406080512054166111065765ffffffffffff421611156110da57610f9d91610f94916134f5565b90929192613531565b6001600160a01b038060805154169116036110ae5760805152601860205260ff604060805120541615611082573447106110525760805182516110149382919060200134855af13d1561104a573d91610ff5836127e0565b9261100360405194856127bd565b83526080513d90602085013e613604565b50608051526019602052604060805120600160ff1982541617905560016001600160a01b03196006541617600655608051608051f35b606091613604565b7fcd7860590000000000000000000000000000000000000000000000000000000060805152306004526024608051fd5b7f8ee6bc3100000000000000000000000000000000000000000000000000000000608051526004608051fd5b7fd2bac4ba00000000000000000000000000000000000000000000000000000000608051526004608051fd5b7f769d11e400000000000000000000000000000000000000000000000000000000608051526004608051fd5b7f756688fe00000000000000000000000000000000000000000000000000000000608051526004608051fd5b5061113c326128fc565b610e5f565b61115a915060203d602011610ae657610ad881836127bd565b86610e57565b346101a3576080516003193601126101a35761117a612c63565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300556001600160a01b0360805191167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0608051608051a360805180f35b346101a35760206003193601126101a3576001600160a01b03611225612724565b1660805152600c60205260606040608051205460ff604051916001600160a01b0381168352818160a01c161515602084015260a81c1615156040820152f35b346101a3576080516003193601126101a3576020600954604051908152f35b346101a3576001600160a01b036112993661273f565b91906112a3612c63565b166080515260186020526040608051209060ff60ff1983541691151516179055608051608051f35b346101a35760206003193601126101a3576001600160a01b036112ec612724565b6112f4612c63565b166001600160a01b03196007541617600755608051608051f35b346101a35760206003193601126101a357611327612724565b61132f612c63565b6001600160a01b038116908160805152600c6020526001600160a01b036040608051205416611a335761136f82600052600b602052604060002054151590565b611a0757602460206001600160a01b0360015416604051928380927f14887c580000000000000000000000000000000000000000000000000000000082528760048301525afa90811561087457608051916119e8575b5015610b1957600254608051546040517f220d32d40000000000000000000000000000000000000000000000000000000081526001600160a01b03938416600482015290831660248201529160209183916044918391165afa90811561087457608051916119c9575b5015610a92576001600160a01b0360055416906001600160a01b03600f541691600454600d54600e546001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416936001600160a01b03601054166001600160a01b0360115416916001600160a01b0360125416936001600160a01b03601354169560405192610160840184811067ffffffffffffffff82111761199957604052808452602084019b8c52604084018960a01c65ffffffffffff168152606085019160ff841615158352608086019360081c60ff161515845260a0860194855260c08601958c875260e0810197885261010081019889526101208101998a5261014001998a526040519d8e916020830152516001600160a01b031690604001525165ffffffffffff1660608d015251151560808c015251151560a08b01525160c08a0152516001600160a01b031660e0890152516001600160a01b0316610100880152516001600160a01b0316610120870152516001600160a01b0316610140860152516001600160a01b031661016085015261016084526115d8610180856127bd565b60405160609490916115ea86846127bd565b6002835260208301601f1987013682378351156119b1573090528251600110156119b157838360409586899601526116f06001600160a01b03601754166116e26016549389519261163a8461276e565b86845260208401526001600160a01b03858b1c168a84015289519261165e8461276e565b83526116b1602084018281528b85019283526001600160a01b038c519c8d966020808901525182815116828901528d836020830151169089015201511660808601525160a08086015260e085019061289c565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030160c085015261289c565b03601f1981018852876127bd565b60145467ffffffffffffffff811691908261193e57506040516117146020826127bd565b608051815260003660208301375b6040519261172f846127a0565b6001845260208401948552604084019687528784019267ffffffffffffffff1683526080840198895260a08401926001845260c0850191825260e08501928352604051998a98899788977fc48927e400000000000000000000000000000000000000000000000000000000895260048901602090525167ffffffffffffffff166024890152516001600160a01b031660448801525160648701610100905261012487016117db91612843565b915167ffffffffffffffff16608487015251908581037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc0160a487015261182191612843565b9251151560c48501525167ffffffffffffffff1660e484015251908281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc0161010484015261187091612843565b0391608051906001600160a01b03165af192831561087457608051936118ec575b50508060805152600c6020526001600160a01b03604060805120921691826001600160a01b03198254161790557f7f74cf9c79e65b11e373ad23da18f4a761fe28401a5a663bbd34ffc2633f5bab608051608051a360805180f35b9080929350813d8311611937575b61190481836127bd565b810103126101a35761192e604061191a836128d9565b92611927602082016128d9565b50016128d9565b50908280611891565b503d6118fa565b60155460408051985091821c65ffffffffffff1691880167ffffffffffffffff811189821017611999578b98602091604052838152019081526040519160208301525160408201526040815261199487826127bd565b611722565b634e487b7160e01b6080515260416004526024608051fd5b634e487b7160e01b6080515260326004526024608051fd5b6119e2915060203d602011610ae657610ad881836127bd565b8261142e565b611a01915060203d602011610ae657610ad881836127bd565b836113c5565b7f7dc7d19c00000000000000000000000000000000000000000000000000000000608051526004608051fd5b7f6b090a6200000000000000000000000000000000000000000000000000000000608051526004608051fd5b346101a3576103006003193601126101a357611a79612724565b6024356001600160a01b038116908190036101a3576044356001600160a01b03811691908290036101a3576064356001600160a01b038116908190036101a3576084356001600160a01b03811693908490036101a35760a4356001600160a01b03811694908590036101a35760c4356001600160a01b03811694908590036101a35760e4359065ffffffffffff821682036101a3576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebc3601126101a3577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549667ffffffffffffffff8816801590816124c2575b60011490816124b8575b1590816124af575b5061248357600167ffffffffffffffff198916177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005560ff8860401c161561242e575b611bcd61349c565b611bd561349c565b611bde33612ba4565b60408051909990611bef8b826127bd565b601081527f48696e6b616c4d6964646c65776172650000000000000000000000000000000060208201528a5190611c268c836127bd565b600182527f31000000000000000000000000000000000000000000000000000000000000006020830152611c5861349c565b80519067ffffffffffffffff8211611999578190611c967fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10254612cc4565b601f81116123b8575b506020906001601f8411146123125760805192612307575b50506000198260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102555b80519067ffffffffffffffff821161199957611d277fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10354612cc4565b601f811161229c575b506020906001601f8411146121e9579180916001600160a01b039493608051926121de575b50506000198260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103555b6080517fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100556080517fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10155166001600160a01b0319608051541617608051556001600160a01b031960055416176005556001600160a01b031960015416176001557fffffffffffff000000000000000000000000000000000000000000000000000079ffffffffffff00000000000000000000000000000000000000006004549260a01b16911617176004556001600160a01b031960025416176002556001600160a01b0319600354161760035561010435600855610124356009556001600160a01b031960075416176007556080515061014435801515908181036101a3575060ff60ff19600d5416911617600d556080515061016435801515908181036101a357507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff61ff00600d549260081b16911617600d5561018435600e55608051506101a4356001600160a01b038116908181036101a357506001600160a01b0319600f541617600f55608051506101c4356001600160a01b038116908181036101a357506001600160a01b03196010541617601055608051506101e4356001600160a01b038116908181036101a357506001600160a01b0319601154161760115560805150610204356001600160a01b038116908181036101a357506001600160a01b0319601254161760125560805150610224356001600160a01b038116908181036101a357506001600160a01b03196013541617601355608051506102443567ffffffffffffffff8116908181036101a3575067ffffffffffffffff1960145416176014556102643565ffffffffffff811681036101a3577fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff6dffffffffffff000000000000000060145492851b1691161760145561028435601555608051506102a43567ffffffffffffffff8116908181036101a3575067ffffffffffffffff196016541617601655608051506102c4356001600160a01b03811681036101a3577fffffffff0000000000000000000000000000000000000000ffffffffffffffff7bffffffffffffffffffffffffffffffffffffffff000000000000000060165492851b16911617601655608051506102e435906001600160a01b0382168083036101a35760ff92506001600160a01b0319601754161760175560016001600160a01b0319600654161760065560401c16156121485760805180f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2917fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555160018152a1806101ef565b015190508d80611d55565b90601f198316917fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103608051528160805120926080515b81811061228457509160019391856001600160a01b039796941061226b575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10355611d89565b015160001960f88460031b161c191690558d808061223e565b9293602060018192878601518155019501930161221f565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10360805152602060805120601f840160051c810191602085106122fd575b601f0160051c01905b8181106122f05750611d30565b60805181556001016122e3565b90915081906122da565b015190508d80611cb7565b608080517fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10290525182812093601f1916905b8181106123a05750908460019594939210612387575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10255611ceb565b015160001960f88460031b161c191690558d808061235a565b92936020600181928786015181550195019301612344565b9091507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10260805152602060805120601f840160051c81019160208510612424575b90601f859493920160051c01905b8181106124145750611c9f565b6080518155849350600101612407565b90915081906123f9565b680100000000000000017fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000008916177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055611bc5565b7ff92ee8a900000000000000000000000000000000000000000000000000000000608051526004608051fd5b9050158a611b82565b303b159150611b7a565b60408a901c60ff16159150611b70565b346101a3576080516003193601126101a35760206001600160a01b0360055416604051908152f35b346101a3576080516003193601126101a35760206001600160a01b0360035416604051908152f35b346101a35760206003193601126101a357600435608051526019602052602060ff60406080512054166040519015158152f35b346101a35760206003193601126101a3576001600160a01b03612576612724565b16608051526018602052602060ff60406080512054166040519015158152f35b346101a3576001600160a01b036125ac3661273f565b91906125b6612c63565b16908160805152600c602052604060805120816000146126c157805460ff8160a81c16612695577fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790556000828152600b602052604090205461265e575b1515907f064709432483b7469e36cc282db9aa95ee5df7d163c25983d72758f36d89227a608051608051a360805180f35b6126678261339f565b50608051827fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18280a361262d565b7f1996476b00000000000000000000000000000000000000000000000000000000608051526004608051fd5b805460ff8160a81c16156126f8577fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16905561262d565b7ff4ef2b3f00000000000000000000000000000000000000000000000000000000608051526004608051fd5b600435906001600160a01b038216820361273a57565b600080fd5b600319604091011261273a576004356001600160a01b038116810361273a5790602435801515810361273a5790565b6060810190811067ffffffffffffffff82111761278a57604052565b634e487b7160e01b600052604160045260246000fd5b610100810190811067ffffffffffffffff82111761278a57604052565b90601f601f19910116810190811067ffffffffffffffff82111761278a57604052565b67ffffffffffffffff811161278a57601f01601f191660200190565b81601f8201121561273a57803590612813826127e0565b9261282160405194856127bd565b8284526020838301011161273a57816000926020809301838601378301015290565b919082519283825260005b84811061286f575050601f19601f8460006020809697860101520116010190565b8060208092840101518282860101520161284e565b9081602091031261273a5751801515810361273a5790565b906020808351928381520192019060005b8181106128ba5750505090565b82516001600160a01b03168452602093840193909201916001016128ad565b51906001600160a01b038216820361273a57565b9081602091031261273a575190565b6001600160a01b038116600052600c6020526001600160a01b03604060002054168015612a4957602060049160405192838092630ce9b79360e41b82525afa9081156129fb57600091612a07575b506000546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156129fb576000916129c9575b50600854111590565b90506020813d6020116129f3575b816129e4602093836127bd565b8101031261273a5751386129c0565b3d91506129d7565b6040513d6000823e3d90fd5b90506020813d602011612a41575b81612a22602093836127bd565b8101031261273a576129ac91612a396020926128d9565b91509161294a565b3d9150612a15565b7fae2411a60000000000000000000000000000000000000000000000000000000060005260046000fd5b6001600160a01b038116600052600c602052600460206001600160a01b036040600020541660405192838092630ce9b79360e41b82525afa9081156129fb57600091612b62575b506000546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156129fb57600091612b33575090565b90506020813d602011612b5a575b81612b4e602093836127bd565b8101031261273a575190565b3d9150612b41565b90506020813d602011612b9c575b81612b7d602093836127bd565b8101031261273a57612b1c91612b946020926128d9565b915091612aba565b3d9150612b70565b6001600160a01b03168015612c34576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b7f1e4fbdf700000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303612c9657565b7f118cdaa7000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b90600182811c92168015612cf4575b6020831014612cde57565b634e487b7160e01b600052602260045260246000fd5b91607f1691612cd3565b604051906000827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025491612d3183612cc4565b8083529260018116908115612dd65750600114612d57575b612d55925003836127bd565b565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102600090815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b818310612dba575050906020612d5592820101612d49565b6020919350806001915483858901015201910190918492612da2565b60209250612d5594915060ff191682840152151560051b820101612d49565b604051906000827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035491612e2883612cc4565b8083529260018116908115612dd65750600114612e4b57612d55925003836127bd565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103600090815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b818310612eae575050906020612d5592820101612d49565b6020919350806001915483858901015201910190918492612e96565b9190612ed583612a73565b92818410613347576000936001600160a01b03821692838652600c6020526001600160a01b036040872054169265ffffffffffff4216906bffffffffffffffffffffffff1980895460601b1616906040517fb13442710000000000000000000000000000000000000000000000000000000081526020816004818a5afa801561333c578a906132f8575b6001600160a01b03915016906040517fbb24fe8a000000000000000000000000000000000000000000000000000000008152602081600481865afa80156132ed578b9061329e575b67ffffffffffffffff9150166002811015613276579185918b959493156000146131ea576020958694613023604051612fe088826127bd565b838152601f1988013689830137604051988997889687957f021a8156000000000000000000000000000000000000000000000000000000008752600487016136f4565b03925af180156131df576131b1575b50505b810390811161319d576008541161304d575b50509050565b60046020859261305c8561339f565b5060405192838092630ce9b79360e41b82525afa801561319257829061314e575b825460601b6bffffffffffffffffffffffff191691506001600160a01b0316803b1561314a576064839260405197889384927f020cf0c200000000000000000000000000000000000000000000000000000000845260048401528760248401528160448401525af193841561313d576040939461312d575b50908152600c602052207fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8154169055803880613047565b81613137916127bd565b386130f5565b50604051903d90823e3d90fd5b8280fd5b506020813d60201161318a575b81613168602093836127bd565b81010312613186576131816001600160a01b03916128d9565b61307d565b5080fd5b3d915061315b565b6040513d84823e3d90fd5b602485634e487b7160e01b81526011600452fd5b816131d092903d106131d8575b6131c881836127bd565b8101906128ed565b503880613032565b503d6131be565b6040513d8a823e3d90fd5b60209586946132426040516131ff88826127bd565b838152601f1988013689830137604051988997889687957f545ce389000000000000000000000000000000000000000000000000000000008752600487016136f4565b03925af180156131df57613258575b5050613035565b8161326e92903d106131d8576131c881836127bd565b503880613251565b60048b7fa739d4e2000000000000000000000000000000000000000000000000000000008152fd5b506020813d6020116132e5575b816132b8602093836127bd565b810103126132e1575167ffffffffffffffff811681036132e15767ffffffffffffffff90612fa7565b8a80fd5b3d91506132ab565b6040513d8d823e3d90fd5b506020813d602011613334575b81613312602093836127bd565b810103126133305761332b6001600160a01b03916128d9565b612f5f565b8980fd5b3d9150613305565b6040513d8c823e3d90fd5b7f8cc309fd0000000000000000000000000000000000000000000000000000000060005260046000fd5b80548210156133895760005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b6000818152600b6020526040902054801561349557600019810181811161347f57600a5490600019820191821161347f5781810361342e575b505050600a54801561341857600019016133f381600a613371565b60001982549160031b1b19169055600a55600052600b60205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61346761343f61345093600a613371565b90549060031b1c928392600a613371565b81939154906000199060031b92831b921b19161790565b9055600052600b6020526040600020553880806133d8565b634e487b7160e01b600052601160045260246000fd5b5050600090565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c16156134cb57565b7fd7e6bcf80000000000000000000000000000000000000000000000000000000060005260046000fd5b81519190604183036135265761351f92506020820151906060604084015193015160001a90613731565b9192909190565b505060009160029190565b91909160048110156135ee578061354757509050565b60006001820361357b577ff645eedf0000000000000000000000000000000000000000000000000000000060005260046000fd5b50600281036135b257827ffce698f70000000000000000000000000000000000000000000000000000000060005260045260246000fd5b90916003600092146135c2575050565b602492507fd78bce0c000000000000000000000000000000000000000000000000000000008252600452fd5b634e487b7160e01b600052602160045260246000fd5b90613643575080511561361957805190602001fd5b7f1425ea420000000000000000000000000000000000000000000000000000000060005260046000fd5b8151158061368b575b613654575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b50803b1561364c565b80600052600b602052604060002054156000146136ee57600a546801000000000000000081101561278a576136d5613450826001859401600a55600a613371565b9055600a5490600052600b602052604060002055600190565b50600090565b919360a0936001600160a01b0361372e979665ffffffffffff94865216602085015260408401521660608201528160808201520190612843565b90565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116137ae579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa156129fb576000516001600160a01b038116156137a25790600090600090565b50600090600190600090565b50505060009160039190565b6137c2612cfe565b80519081156137d2576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1005480156137ff5790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b61382c612df5565b805190811561383c576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1015480156137ff579056fea26469706673582212202425e882d09aad0060af28551240162671c467ba9c0c881999ef30eb50c6e21864736f6c634300081b0033
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.