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:
HinkalMiddlewareOld
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 } from "@symbioticfi/core/src/interfaces/delegator/IFullRestakeDelegator.sol"; // import { IOperatorSpecificDelegator, IBaseDelegator } from "./symbiotic-core/interfaces/delegator/IOperatorSpecificDelegator.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 HinkalMiddlewareOld is IHinkalMiddleware, Initializable, EIP712Upgradeable, OwnableUpgradeable { bytes32 private constant EXECUTE_TYPEHASH = keccak256("NetworkPermit(address operator,address endpoint,bytes payload)"); using EnumerableSet for EnumerableSet.AddressSet; using Subnetwork for address; error UnknownSlasherType(); error NotNetwork(); error OperatorAlreadyRegistred(); error NotOperator(); error OperatorVaultNotOptedIn(); error OperatorNetworkNotOptedIn(); error OperatorIsBlacklisted(); error OperatorNotRegistred(); error OperatorAlreadyEnabled(); error OperatorAlreadyBlacklisted(); error TooBigSlashAmount(); error NotWhitelistedEndpoint(); error NotSignedByNetwork(); error NotValidOperator(); event OperatorAndVaultSet(address indexed operator, address indexed vault); event OperatorEnabled(address indexed operator, bool indexed enable); event OperatorBlacklisted(address indexed operator, bool indexed blacklist); event Executed(address indexed endpoint); event Slashed(address indexed operator, uint256 amount); event EndpointWhitelisted(address indexed endpoint, bool indexed val); event HinkalHelperChanged(address indexed oldAddress, address indexed newAddress); // 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; EnumerableSet.AddressSet private endpoints; 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 { 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() { relayer = tx.origin; _; relayer = address(1); } modifier onlyOperator() { require( IHinkalHelper(hinkalHelper).isRelayInList(tx.origin) || isValidOperator(tx.origin), NotValidOperator() ); _; } 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), OperatorAlreadyRegistred()); require(IRegistry(OPERATOR_REGISTRY).isEntity(operator), NotOperator()); require( IOptInService(OPERATOR_NET_OPTIN).isOptedIn(operator, NETWORK), OperatorNetworkNotOptedIn() ); 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[](3); networkSetterRoles[0] = address(this); networkSetterRoles[1] = owner(); networkSetterRoles[2] = NETWORK; 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: 2, delegatorParams: delegatorParams, withSlasher: true, slasherIndex: defaultVaultParams.slasherInitParams.slasherIndex, slasherParams: slahserParams }); (address vault, , ) = IVaultConfigurator(VAULT_CONFIGURATOR).create(configuratorParams); operatorInfos[operator].vault = vault; emit OperatorAndVaultSet(operator, vault); } function setOperatorState(address operator) public virtual { OperatorInfo storage operatorInfo = operatorInfos[operator]; require(!operatorInfo.isBlacklisted, OperatorIsBlacklisted()); require( IOptInService(OPERATOR_VAULT_OPTIN).isOptedIn(operator, operatorInfo.vault), OperatorVaultNotOptedIn() ); IFullRestakeDelegator delegator = IFullRestakeDelegator( IVault(operatorInfo.vault).delegator() ); if (delegator.networkLimit(NETWORK.subnetwork(0)) != type(uint256).max) { delegator.setNetworkLimit(NETWORK.subnetwork(0), type(uint256).max); } uint256 opStake = IVault(operatorInfo.vault).activeShares(); if (opStake >= minimumStake) { delegator.setOperatorNetworkLimit(NETWORK.subnetwork(0), operator, type(uint256).max); // operators.add(operator); operatorInfo.enabled = true; emit OperatorEnabled(operator, true); } else { delegator.setOperatorNetworkLimit(NETWORK.subnetwork(0), operator, 0); // operators.remove(operator); operatorInfo.enabled = false; emit OperatorEnabled(operator, false); } } // NOTE: maybe onlyOnwer should be changed to 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 (operatorInfo.enabled = true) { operatorInfo.enabled = false; 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 { val ? endpoints.add(endpoint) : endpoints.remove(endpoint); emit EndpointWhitelisted(endpoint, val); } function setHinkalHelper(address newHinkalHelper) external virtual onlyOwner { emit HinkalHelperChanged(hinkalHelper, newHinkalHelper); 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 - 1), vault, NETWORK.subnetwork(0), operator, amount); uint256 stake = totalOperatorStake - amount; if (stake < minimumStake) { operatorInfos[operator].enabled = false; } emit Slashed(operator, amount); } 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, bytes memory payload, bytes memory signature ) external payable onlyOperator setRelayerForHinkal { require(endpoints.contains(endpoint), NotWhitelistedEndpoint()); bytes32 structHash = keccak256( abi.encode(EXECUTE_TYPEHASH, tx.origin, endpoint, keccak256(payload)) ); bytes32 hash = _hashTypedDataV4(structHash); require(ECDSA.recover(hash, signature) == NETWORK, NotSignedByNetwork()); Address.functionCallWithValue(endpoint, payload, msg.value); emit Executed(endpoint); } 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)); } } function isWhitelistedEndpoint(address endpoint) external view returns (bool) { return endpoints.contains(endpoint); } function getAllWhitelistedEndpoints() external view returns (address[] memory endpointsArr) { uint256 len = endpoints.length(); endpointsArr = new address[](len); for (uint256 i = 0; i < len; i++) { endpointsArr[i] = endpoints.at(i); } } function whitelistedEndpointsAmount() external view returns (uint256) { return endpoints.length(); } function endpointAtIndex(uint256 i) external view returns (address) { return endpoints.at(i); } /// @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; 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":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NotNetwork","type":"error"},{"inputs":[],"name":"NotOperator","type":"error"},{"inputs":[],"name":"NotSignedByNetwork","type":"error"},{"inputs":[],"name":"NotValidOperator","type":"error"},{"inputs":[],"name":"NotWhitelistedEndpoint","type":"error"},{"inputs":[],"name":"OperatorAlreadyBlacklisted","type":"error"},{"inputs":[],"name":"OperatorAlreadyEnabled","type":"error"},{"inputs":[],"name":"OperatorAlreadyRegistred","type":"error"},{"inputs":[],"name":"OperatorIsBlacklisted","type":"error"},{"inputs":[],"name":"OperatorNetworkNotOptedIn","type":"error"},{"inputs":[],"name":"OperatorNotRegistred","type":"error"},{"inputs":[],"name":"OperatorVaultNotOptedIn","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":"TooBigSlashAmount","type":"error"},{"inputs":[],"name":"UnknownSlasherType","type":"error"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"endpoint","type":"address"},{"indexed":true,"internalType":"bool","name":"val","type":"bool"}],"name":"EndpointWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"endpoint","type":"address"}],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":true,"internalType":"address","name":"newAddress","type":"address"}],"name":"HinkalHelperChanged","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Slashed","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 HinkalMiddlewareOld.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 HinkalMiddlewareOld.SlasherInitParams","name":"slasherInitParams","type":"tuple"},{"components":[{"internalType":"address","name":"hookSetRoleHolder","type":"address"},{"internalType":"address","name":"hook","type":"address"}],"internalType":"struct HinkalMiddlewareOld.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":"uint256","name":"i","type":"uint256"}],"name":"endpointAtIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"endpoint","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getAllWhitelistedEndpoints","outputs":[{"internalType":"address[]","name":"endpointsArr","type":"address[]"}],"stateMutability":"view","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 HinkalMiddlewareOld.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 HinkalMiddlewareOld.SlasherInitParams","name":"slasherInitParams","type":"tuple"},{"components":[{"internalType":"address","name":"hookSetRoleHolder","type":"address"},{"internalType":"address","name":"hook","type":"address"}],"internalType":"struct HinkalMiddlewareOld.DelegatorInitParams","name":"delegatorInitParams","type":"tuple"}],"internalType":"struct HinkalMiddlewareOld.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":"endpoint","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":"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"},{"inputs":[],"name":"whitelistedEndpointsAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080806040523460d2577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c1660c1576002600160401b03196001600160401b03821601605c575b6040516137bf90816100d88239f35b6001600160401b0319166001600160401b039081177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a13880604d565b63f92ee8a960e01b60005260046000fd5b600080fdfe6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c8062ff0794146125775780630da7d0431461253c57806318b01c1f1461251557806324bbab8b146124ee5780633682a45014611db1578063393cf40714611d935780633abd53ca14611d235780634d34d5ce14611cb25780636343b15f14611c945780636d5149c014611c37578063715018a614611b9e57806383ce032214611b775780638406c07914611b5057806384b0196e146119c55780638759e6d11461199f5780638da5cb5b1461195957806390c88c8a14611922578063911e928d1461140b57806393fe3889146113e45780639671084a146113bd5780639a76de1114611310578063a73f4dac14611156578063b25bc0c01461112f578063c96be4cb146110c4578063cc11e0be1461109b578063d4fa453414610d25578063d7bf2a30146102dc578063e2d53d7c146102ae578063e4e88de814610282578063ec14c5e514610222578063ec5ffac214610204578063f2fde38b146101d7578063f4595b89146101bb5763fefdc6c41461019c575061000e565b346101b857806003193601126101b85760206040516127108152f35b80fd5b50346101b857806003193601126101b857602060405160018152f35b50346101b85760206003193601126101b8576102016101f46126cf565b6101fc612c6f565b612bb0565b80f35b50346101b857806003193601126101b8576020600854604051908152f35b50346101b85760406003193601126101b85761023c6126cf565b6001600160a01b03825416330361025a576102019060243590612ef4565b6004827f8f54ee5c000000000000000000000000000000000000000000000000000000008152fd5b50346101b85760206003193601126101b85760206102a66102a16126cf565b612a66565b604051908152f35b50346101b85760206003193601126101b85760206102d26102cd6126cf565b6128d6565b6040519015158152f35b50346101b8576102e06003193601126101b8576102f76126cf565b6024356001600160a01b038116809103610d2157604435906001600160a01b0382168092036109d5576064356001600160a01b0381168091036109d157608435926001600160a01b038416809403610d1d5760a435936001600160a01b0385168095036109d95760c435936001600160a01b038516809503610d195765ffffffffffff60e4351660e43503610d19576101a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebc360112610d19577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549560ff8760401c16159667ffffffffffffffff811680159081610d11575b6001149081610d07575b159081610cfe575b50610cd6578760017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008316177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055610c81575b5061045f6135f8565b6104676135f8565b61047033612bb0565b6040978851906104808a836127fd565b601082527f48696e6b616c4d6964646c65776172650000000000000000000000000000000060208301528951916104b78b846127fd565b600183527f310000000000000000000000000000000000000000000000000000000000000060208401526104e96135f8565b80519067ffffffffffffffff8211610c6d578c82916105287fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10254612cd0565b601f8111610bdc575b50602091601f8411600114610b3b5792610b30575b50506000198260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102555b815167ffffffffffffffff8111610b1c576105b57fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10354612cd0565b601f8111610a95575b5060208c601f83116001146109e857906001600160a01b0394836109dd575b50506000198260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103555b8a7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100558a7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10155166001600160a01b03198a54161789556001600160a01b031960055416176005556001600160a01b031960015416176001556004547fffffffffffff000000000000000000000000000000000000000000000000000079ffffffffffff000000000000000000000000000000000000000060e43560a01b16911617176004556001600160a01b031960025416176002556001600160a01b0319600354161760035561010435600855610124356009556001600160a01b0319600754161760075561014435801515908181036109d15750600b54610164358015158082036109d95761ff0060ff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000935060081b16931691161717600b5561018435600c556101a4356001600160a01b038116908181036109d157506001600160a01b0319600d541617600d556101c4356001600160a01b038116908181036109d157506001600160a01b0319600e541617600e556101e4356001600160a01b038116908181036109d157506001600160a01b0319600f541617600f55610204356001600160a01b038116908181036109d157506001600160a01b03196010541617601055610224356001600160a01b038116908181036109d157506001600160a01b031960115416176011556102443567ffffffffffffffff81168091036109d5577fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000060125416176012556102643565ffffffffffff811681036109d5577fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff6dffffffffffff000000000000000060125492851b16911617601255610284356013556102a4356001600160a01b038116908181036109d157506001600160a01b031960145416176014556102c4356001600160a01b038116908181036109d157506001600160a01b0319601554161760155560016001600160a01b0319600654161760065561093e575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2917fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555160018152a180f35b8480fd5b8380fd5b8680fd5b0151905038806105dd565b919293601f1984167fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1038452828420935b818110610a7d57509160019391856001600160a01b0397969410610a64575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10355610611565b015160001960f88460031b161c19169055388080610a37565b92936020600181928786015181550195019301610a18565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1038d527f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b75601f830160051c81019160208410610b12575b601f0160051c01908d905b828110610b055750506105be565b9081558d90600101610af7565b9091508190610aec565b60248c634e487b7160e01b81526041600452fd5b015190503880610546565b92601f19167fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1028452828420935b818110610bc45750908460019594939210610bab575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025561057a565b015160001960f88460031b161c19169055388080610b7e565b92936020600181928786015181550195019301610b68565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10290925291507f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d601f840160051c81019160208510610c63575b918f9291601f8695930160051c01905b818110610c535750610531565b9283558493508f92600101610c46565b9091508190610c36565b60248d634e487b7160e01b81526041600452fd5b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005538610456565b60048a7ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b90501538610403565b303b1591506103fb565b8991506103f1565b8780fd5b8580fd5b8280fd5b5060606003193601126101b857610d3a6126cf565b60243567ffffffffffffffff8111610d2157610d5a90369060040161283c565b9060443567ffffffffffffffff81116109d557610d7b90369060040161283c565b602460206001600160a01b0360075416604051928380927f946b30ef0000000000000000000000000000000000000000000000000000000082523260048301525afa908115611090578591611061575b508015611052575b1561102a57326001600160a01b031960065416176006556001600160a01b03821692610e0c846000526017602052604060002054151590565b1561100257610f16610f0d82519360426020850195862060405160208101917f510f376a801a09772ac2abbd61d60d4a60500adc79f9adc1fca2c043965eb6e983523260408301528a6060830152608082015260808152610e6e60a0826127fd565b519020610e796136da565b610e81613744565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a08152610ed260c0826127fd565b51902090604051917f190100000000000000000000000000000000000000000000000000000000000083526002830152602282015220613459565b90929192613495565b6001600160a01b0380875416911603610fda57344710610fae5784610f6b93928192519034855af13d15610fa6573d91610f4f83612820565b92610f5d60405194856127fd565b83523d86602085013e613568565b507fdf42bfa876a741bbe542cf1a563269e1390bf03901b5d433a6e8afd6ee36dbfe8280a260016001600160a01b0319600654161760065580f35b606091613568565b6024857fcd78605900000000000000000000000000000000000000000000000000000000815230600452fd5b6004857fd2bac4ba000000000000000000000000000000000000000000000000000000008152fd5b6004857f8ee6bc31000000000000000000000000000000000000000000000000000000008152fd5b6004847f5e087564000000000000000000000000000000000000000000000000000000008152fd5b5061105c326128d6565b610dd3565b611083915060203d602011611089575b61107b81836127fd565b810190612883565b38610dcb565b503d611071565b6040513d87823e3d90fd5b50346101b857806003193601126101b857602065ffffffffffff60045460a01c16604051908152f35b50346101b85760206003193601126101b8576110de6126cf565b6001600160a01b03825416330361025a576110f881612a66565b6009549081810291818304149015171561111b5790612710610201920490612ef4565b602483634e487b7160e01b81526011600452fd5b50346101b857806003193601126101b85760206001600160a01b0360045416604051908152f35b50346101b857806003193601126101b857604051611173816127e0565b600b5460ff811615158252602082019060081c60ff1615158152600c5460408301908152600d546001600160a01b031660608401908152600e546001600160a01b031660808501908152600f546001600160a01b031660a086019081526010546001600160a01b031660c087019081526011546001600160a01b03169060e088019182526040519261120484612792565b6012549467ffffffffffffffff86168552602085019560401c65ffffffffffff16865260135496604086019788526040519861123f8a6127c4565b6014546001600160a01b03168a526015546001600160a01b03169a60208b019b8c526040519c5115158d5251151560208d01525160408c0152516001600160a01b031660608b0152516001600160a01b031660808a0152516001600160a01b031660a0890152516001600160a01b031660c0880152516001600160a01b031660e08701525167ffffffffffffffff166101008601525165ffffffffffff1661012085015251610140840152516001600160a01b0316610160830152516001600160a01b03166101808201526101a090f35b50346101b857806003193601126101b85760165461132d8161289b565b9161133b60405193846127fd565b818352601f1961134a8361289b565b01366020850137805b828110611374576040516020808252819061137090820187612755565b0390f35b6001600160a01b036113858261328c565b90549060031b1c1684518210156113a957600582901b850160200152600101611353565b602483634e487b7160e01b81526032600452fd5b50346101b857806003193601126101b85760206001600160a01b0360075416604051908152f35b50346101b857806003193601126101b85760206001600160a01b0360025416604051908152f35b50346101b85760206003193601126101b8576114256126cf565b6001600160a01b038116808352600a602052604083209182549060ff8260a81c166118fa576003546040517f220d32d40000000000000000000000000000000000000000000000000000000081526001600160a01b03928316600482015292821660248401819052929160209183916044918391165afa9081156110905785916118db575b50156118b357600460208592604051928380927fce9b79300000000000000000000000000000000000000000000000000000000082525afa801561169a57829061186f575b6001600160a01b039150166bffffffffffffffffffffffff1980835460601b16166040517f3eb22c0f000000000000000000000000000000000000000000000000000000008152816004820152602081602481865afa801561177d57849061183b575b6000199150036117cd575b50600460206001600160a01b03865416604051928380927fbfefcd7b0000000000000000000000000000000000000000000000000000000082525afa9081156117c2578391611788575b50600854116116a557815460601b6bffffffffffffffffffffffff1916813b15610d215782916064839260405194859384927f020cf0c2000000000000000000000000000000000000000000000000000000008452600484015288602484015260001960448401525af1801561169a57611685575b505081740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff60019454161790557fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18380a380f35b8161168f916127fd565b610d2157823861161c565b6040513d84823e3d90fd5b815491939160601b6bffffffffffffffffffffffff1916813b156109d15784916064839260405194859384927f020cf0c200000000000000000000000000000000000000000000000000000000845260048401528860248401528160448401525af190811561177d578491611764575b50507fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff81541690557fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18280a380f35b8161176e916127fd565b611779578238611715565b5050fd5b6040513d86823e3d90fd5b9250506020823d6020116117ba575b816117a4602093836127fd565b810103126117b557849151386115a7565b600080fd5b3d9150611797565b6040513d85823e3d90fd5b908092503b156109d157604051907f0214534800000000000000000000000000000000000000000000000000000000825260048201526000196024820152848160448183865af1801561109057611827575b90849161155d565b84611834919592956127fd565b923861181f565b506020813d602011611867575b81611855602093836127fd565b810103126109d5576000199051611552565b3d9150611848565b506020813d6020116118ab575b81611889602093836127fd565b810103126118a7576118a26001600160a01b03916128b3565b6114ef565b5080fd5b3d915061187c565b6004847f439536aa000000000000000000000000000000000000000000000000000000008152fd5b6118f4915060203d6020116110895761107b81836127fd565b386114aa565b6004857f23daf16a000000000000000000000000000000000000000000000000000000008152fd5b50346101b85760206003193601126101b85760206001600160a01b0361194960043561328c565b90549060031b1c16604051908152f35b50346101b857806003193601126101b85760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b50346101b857806003193601126101b8576001600160a01b036020915416604051908152f35b50346101b857806003193601126101b8577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100541580611b27575b15611ac957611a6d90611a10612d0a565b90611a19612e1f565b906020611a7b60405193611a2d83866127fd565b838552833681376040519687967f0f00000000000000000000000000000000000000000000000000000000000000885260e08589015260e0880190612714565b908682036040880152612714565b904660608601523060808601528260a086015284820360c08601528080855193848152019401925b828110611ab257505050500390f35b835185528695509381019392810192600101611aa3565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10154156119ff565b50346101b857806003193601126101b85760206001600160a01b0360065416604051908152f35b50346101b857806003193601126101b85760206001600160a01b0360015416604051908152f35b50346101b857806003193601126101b857611bb7612c6f565b806001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101b85760206003193601126101b85760406060916001600160a01b03611c5e6126cf565b168152600a602052205460ff604051916001600160a01b0381168352818160a01c161515602084015260a81c1615156040820152f35b50346101b857806003193601126101b8576020600954604051908152f35b50346101b8576001600160a01b03611cc9366126e5565b611cd4929192612c6f565b8015611d1257611ce58284166133bc565b505b151591167f5843bb05b84b2214eccaba0184a247ce2d47dba5292382aa88eb70a55522173a8380a380f35b611d1d8284166132d5565b50611ce7565b50346101b85760206003193601126101b857611d3d6126cf565b611d45612c6f565b6001600160a01b03196001600160a01b03600754921691826001600160a01b0382167f7fcf72baecc3134a31915febb8df705e0551f38069d9cb26de2c0da33b7a86978680a3161760075580f35b50346101b857806003193601126101b8576020601654604051908152f35b50346101b85760206003193601126101b857611dcb6126cf565b611dd3612c6f565b6001600160a01b038116808352600a6020526001600160a01b036040842054166124c657602460206001600160a01b0360015416604051928380927f14887c580000000000000000000000000000000000000000000000000000000082528660048301525afa90811561177d5784916124a7575b501561247f5760025483546040517f220d32d40000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201529084166024820181905293909160209183916044918391165afa90811561177d578491612460575b5015612438576001600160a01b0360055416916001600160a01b03600d54169260045491600b54600c546001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416936001600160a01b03600e54166001600160a01b03600f5416916001600160a01b0360105416936001600160a01b03601154169560405192610160840184811067ffffffffffffffff82111761242457604052808452602084019c8d5260408401908b60a01c65ffffffffffff168252606085019160ff841615158352608086019360081c60ff161515845260a0860194855260c08601958c875260e0810197885261010081019889526101208101998a5261014001998a526040519e8f926020840152516001600160a01b031660408301525165ffffffffffff16906060015251151560808d015251151560a08c01525160c08b0152516001600160a01b031660e08a0152516001600160a01b0316610100890152516001600160a01b0316610120880152516001600160a01b0316610140870152516001600160a01b0316610160860152610160855261205c610180866127fd565b6040519061206b6080836127fd565b60038252602082016060368237825115612410573090528151600110156123fc578260408301528151600210156123fc578161217a916060604094015261216c6001600160a01b0360155416916001600160a01b03601454168551936120d085612792565b8785526020850152858401528451926120e884612792565b835261213b602084018281528685019283526001600160a01b03875197889660208089015251828151168289015282602082015116606089015201511660808601525160a08086015260e0850190612755565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030160c0850152612755565b03601f1981018352826127fd565b60125467ffffffffffffffff81169190826123b5575060405161219e6020826127fd565b87815260003660208301375b604051926121b7846127e0565b60018452602084019485526040840197885260608401600281526080850193845260a08501936001855260c0860192835260e08601938452604051998a9788977fc48927e400000000000000000000000000000000000000000000000000000000895260048901602090525167ffffffffffffffff166024890152516001600160a01b0316604488015251606487016101009052610124870161225991612714565b915167ffffffffffffffff16608487015251908581037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc0160a487015261229f91612714565b9251151560c48501525167ffffffffffffffff1660e484015251908281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc016101048401526122ee91612714565b03916001600160a01b03169181865a94606095f19182156117c257839261235f575b50808352600a6020526001600160a01b0360408420921691826001600160a01b03198254161790557f7f74cf9c79e65b11e373ad23da18f4a761fe28401a5a663bbd34ffc2633f5bab8380a380f35b9091506060813d6060116123ad575b8161237b606093836127fd565b81010312610d21576123a56040612391836128b3565b9261239e602082016128b3565b50016128b3565b509038612310565b3d915061236e565b65ffffffffffff9060401c1660135460206040516123d2816127c4565b83815201908152604051916020830152516040820152604081526123f76060826127fd565b6121aa565b602487634e487b7160e01b81526032600452fd5b602488634e487b7160e01b81526032600452fd5b60248f634e487b7160e01b81526041600452fd5b6004837f424e73c5000000000000000000000000000000000000000000000000000000008152fd5b612479915060203d6020116110895761107b81836127fd565b38611eb0565b6004837f7c214f04000000000000000000000000000000000000000000000000000000008152fd5b6124c0915060203d6020116110895761107b81836127fd565b38611e47565b6004837f7dc7d19c000000000000000000000000000000000000000000000000000000008152fd5b50346101b857806003193601126101b85760206001600160a01b0360055416604051908152f35b50346101b857806003193601126101b85760206001600160a01b0360035416604051908152f35b50346101b85760206003193601126101b85760206102d26001600160a01b036125636126cf565b166000526017602052604060002054151590565b50346101b8576001600160a01b0361258e366126e5565b9190612598612c6f565b1690818352600a602052604083208160001461267057805460ff8160a81c16612648577fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff16750100000000000000000000000000000000000000000017905582827fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18280a35b1515907f064709432483b7469e36cc282db9aa95ee5df7d163c25983d72758f36d89227a8380a380f35b6004857f1996476b000000000000000000000000000000000000000000000000000000008152fd5b805460ff8160a81c16156126a7577fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16905561261e565b6004857ff4ef2b3f000000000000000000000000000000000000000000000000000000008152fd5b600435906001600160a01b03821682036117b557565b60031960409101126117b5576004356001600160a01b03811681036117b5579060243580151581036117b55790565b919082519283825260005b848110612740575050601f19601f8460006020809697860101520116010190565b8060208092840101518282860101520161271f565b906020808351928381520192019060005b8181106127735750505090565b82516001600160a01b0316845260209384019390920191600101612766565b6060810190811067ffffffffffffffff8211176127ae57604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176127ae57604052565b610100810190811067ffffffffffffffff8211176127ae57604052565b90601f601f19910116810190811067ffffffffffffffff8211176127ae57604052565b67ffffffffffffffff81116127ae57601f01601f191660200190565b81601f820112156117b55780359061285382612820565b9261286160405194856127fd565b828452602083830101116117b557816000926020809301838601378301015290565b908160209103126117b5575180151581036117b55790565b67ffffffffffffffff81116127ae5760051b60200190565b51906001600160a01b03821682036117b557565b908160209103126117b5575190565b6001600160a01b038116600052600a6020526001600160a01b03604060002054168015612a3c576020600491604051928380927fce9b79300000000000000000000000000000000000000000000000000000000082525afa9081156129ee576000916129fa575b506000546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156129ee576000916129bc575b50600854111590565b90506020813d6020116129e6575b816129d7602093836127fd565b810103126117b55751386129b3565b3d91506129ca565b6040513d6000823e3d90fd5b90506020813d602011612a34575b81612a15602093836127fd565b810103126117b55761299f91612a2c6020926128b3565b91509161293d565b3d9150612a08565b7fae2411a60000000000000000000000000000000000000000000000000000000060005260046000fd5b6001600160a01b038116600052600a602052600460206001600160a01b0360406000205416604051928380927fce9b79300000000000000000000000000000000000000000000000000000000082525afa9081156129ee57600091612b6e575b506000546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156129ee57600091612b3f575090565b90506020813d602011612b66575b81612b5a602093836127fd565b810103126117b5575190565b3d9150612b4d565b90506020813d602011612ba8575b81612b89602093836127fd565b810103126117b557612b2891612ba06020926128b3565b915091612ac6565b3d9150612b7c565b6001600160a01b03168015612c40576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b7f1e4fbdf700000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303612ca257565b7f118cdaa7000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b90600182811c92168015612d00575b6020831014612cea57565b634e487b7160e01b600052602260045260246000fd5b91607f1691612cdf565b604051906000827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025491612d3d83612cd0565b8083529260018116908115612de25750600114612d63575b612d61925003836127fd565b565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102600090815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b818310612dc6575050906020612d6192820101612d55565b6020919350806001915483858901015201910190918492612dae565b60209250612d619491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101612d55565b604051906000827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035491612e5283612cd0565b8083529260018116908115612de25750600114612e7557612d61925003836127fd565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103600090815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b818310612ed8575050906020612d6192820101612d55565b6020919350806001915483858901015201910190918492612ec0565b90612efe82612a66565b818110613262576001600160a01b0383169283600052600a6020526001600160a01b036040600020541660001942014281116130dd5765ffffffffffff1690600460206bffffffffffffffffffffffff198060005460601b161692604051928380927fb13442710000000000000000000000000000000000000000000000000000000082525afa80156129ee57600090613222575b6001600160a01b039150166040517fbb24fe8a000000000000000000000000000000000000000000000000000000008152602081600481855afa9081156129ee576000916131d7575b5067ffffffffffffffff169060028210156131ad57600094879261312157602095869461305260405161300f88826127fd565b838152601f1988013689830137604051988997889687957f021a81560000000000000000000000000000000000000000000000000000000087526004870161341c565b03925af180156129ee576130f3575b50505b8181039081116130dd577f4ed05e9673c26d2ed44f7ef6a7f2942df0ee3b5e1e17db4b99f9dcd261a339cd91602091600854116130a5575b604051908152a2565b83600052600a825260406000207fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff815416905561309c565b634e487b7160e01b600052601160045260246000fd5b8161311292903d1061311a575b61310a81836127fd565b8101906128c7565b503880613061565b503d613100565b602095869461317960405161313688826127fd565b838152601f1988013689830137604051988997889687957f545ce3890000000000000000000000000000000000000000000000000000000087526004870161341c565b03925af180156129ee5761318f575b5050613064565b816131a592903d1061311a5761310a81836127fd565b503880613188565b7fa739d4e20000000000000000000000000000000000000000000000000000000060005260046000fd5b6020813d60201161321a575b816131f0602093836127fd565b810103126118a757519067ffffffffffffffff821682036101b8575067ffffffffffffffff612fdc565b3d91506131e3565b506020813d60201161325a575b8161323c602093836127fd565b810103126117b5576132556001600160a01b03916128b3565b612f93565b3d915061322f565b7f8cc309fd0000000000000000000000000000000000000000000000000000000060005260046000fd5b6016548110156132a757601660005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b80548210156132a75760005260206000200190600090565b60008181526017602052604090205480156133b55760001981018181116130dd576016549060001982019182116130dd57818103613364575b505050601654801561334e57600019016133298160166132bd565b60001982549160031b1b19169055601655600052601760205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61339d6133756133869360166132bd565b90549060031b1c92839260166132bd565b81939154906000199060031b92831b921b19161790565b9055600052601760205260406000205538808061330e565b5050600090565b8060005260176020526040600020541560001461341657601654680100000000000000008110156127ae576133fd61338682600185940160165560166132bd565b9055601654906000526017602052604060002055600190565b50600090565b919360a0936001600160a01b03613456979665ffffffffffff94865216602085015260408401521660608201528160808201520190612714565b90565b815191906041830361348a5761348392506020820151906060604084015193015160001a90613651565b9192909190565b505060009160029190565b919091600481101561355257806134ab57509050565b6000600182036134df577ff645eedf0000000000000000000000000000000000000000000000000000000060005260046000fd5b506002810361351657827ffce698f70000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9091600360009214613526575050565b602492507fd78bce0c000000000000000000000000000000000000000000000000000000008252600452fd5b634e487b7160e01b600052602160045260246000fd5b906135a7575080511561357d57805190602001fd5b7f1425ea420000000000000000000000000000000000000000000000000000000060005260046000fd5b815115806135ef575b6135b8575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b50803b156135b0565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561362757565b7fd7e6bcf80000000000000000000000000000000000000000000000000000000060005260046000fd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116136ce579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa156129ee576000516001600160a01b038116156136c25790600090600090565b50600090600190600090565b50505060009160039190565b6136e2612d0a565b80519081156136f2576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10054801561371f5790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b61374c612e1f565b805190811561375c576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10154801561371f579056fea2646970667358221220ad886350c6210110bf4f2dee90f26905a8b1bdaf8d47836e098d09a0fba3102164736f6c634300081b0033
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c8062ff0794146125775780630da7d0431461253c57806318b01c1f1461251557806324bbab8b146124ee5780633682a45014611db1578063393cf40714611d935780633abd53ca14611d235780634d34d5ce14611cb25780636343b15f14611c945780636d5149c014611c37578063715018a614611b9e57806383ce032214611b775780638406c07914611b5057806384b0196e146119c55780638759e6d11461199f5780638da5cb5b1461195957806390c88c8a14611922578063911e928d1461140b57806393fe3889146113e45780639671084a146113bd5780639a76de1114611310578063a73f4dac14611156578063b25bc0c01461112f578063c96be4cb146110c4578063cc11e0be1461109b578063d4fa453414610d25578063d7bf2a30146102dc578063e2d53d7c146102ae578063e4e88de814610282578063ec14c5e514610222578063ec5ffac214610204578063f2fde38b146101d7578063f4595b89146101bb5763fefdc6c41461019c575061000e565b346101b857806003193601126101b85760206040516127108152f35b80fd5b50346101b857806003193601126101b857602060405160018152f35b50346101b85760206003193601126101b8576102016101f46126cf565b6101fc612c6f565b612bb0565b80f35b50346101b857806003193601126101b8576020600854604051908152f35b50346101b85760406003193601126101b85761023c6126cf565b6001600160a01b03825416330361025a576102019060243590612ef4565b6004827f8f54ee5c000000000000000000000000000000000000000000000000000000008152fd5b50346101b85760206003193601126101b85760206102a66102a16126cf565b612a66565b604051908152f35b50346101b85760206003193601126101b85760206102d26102cd6126cf565b6128d6565b6040519015158152f35b50346101b8576102e06003193601126101b8576102f76126cf565b6024356001600160a01b038116809103610d2157604435906001600160a01b0382168092036109d5576064356001600160a01b0381168091036109d157608435926001600160a01b038416809403610d1d5760a435936001600160a01b0385168095036109d95760c435936001600160a01b038516809503610d195765ffffffffffff60e4351660e43503610d19576101a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebc360112610d19577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549560ff8760401c16159667ffffffffffffffff811680159081610d11575b6001149081610d07575b159081610cfe575b50610cd6578760017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008316177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055610c81575b5061045f6135f8565b6104676135f8565b61047033612bb0565b6040978851906104808a836127fd565b601082527f48696e6b616c4d6964646c65776172650000000000000000000000000000000060208301528951916104b78b846127fd565b600183527f310000000000000000000000000000000000000000000000000000000000000060208401526104e96135f8565b80519067ffffffffffffffff8211610c6d578c82916105287fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10254612cd0565b601f8111610bdc575b50602091601f8411600114610b3b5792610b30575b50506000198260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102555b815167ffffffffffffffff8111610b1c576105b57fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10354612cd0565b601f8111610a95575b5060208c601f83116001146109e857906001600160a01b0394836109dd575b50506000198260011b9260031b1c1916177fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103555b8a7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100558a7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10155166001600160a01b03198a54161789556001600160a01b031960055416176005556001600160a01b031960015416176001556004547fffffffffffff000000000000000000000000000000000000000000000000000079ffffffffffff000000000000000000000000000000000000000060e43560a01b16911617176004556001600160a01b031960025416176002556001600160a01b0319600354161760035561010435600855610124356009556001600160a01b0319600754161760075561014435801515908181036109d15750600b54610164358015158082036109d95761ff0060ff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000935060081b16931691161717600b5561018435600c556101a4356001600160a01b038116908181036109d157506001600160a01b0319600d541617600d556101c4356001600160a01b038116908181036109d157506001600160a01b0319600e541617600e556101e4356001600160a01b038116908181036109d157506001600160a01b0319600f541617600f55610204356001600160a01b038116908181036109d157506001600160a01b03196010541617601055610224356001600160a01b038116908181036109d157506001600160a01b031960115416176011556102443567ffffffffffffffff81168091036109d5577fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000060125416176012556102643565ffffffffffff811681036109d5577fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff6dffffffffffff000000000000000060125492851b16911617601255610284356013556102a4356001600160a01b038116908181036109d157506001600160a01b031960145416176014556102c4356001600160a01b038116908181036109d157506001600160a01b0319601554161760155560016001600160a01b0319600654161760065561093e575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2917fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00555160018152a180f35b8480fd5b8380fd5b8680fd5b0151905038806105dd565b919293601f1984167fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1038452828420935b818110610a7d57509160019391856001600160a01b0397969410610a64575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10355610611565b015160001960f88460031b161c19169055388080610a37565b92936020600181928786015181550195019301610a18565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1038d527f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b75601f830160051c81019160208410610b12575b601f0160051c01908d905b828110610b055750506105be565b9081558d90600101610af7565b9091508190610aec565b60248c634e487b7160e01b81526041600452fd5b015190503880610546565b92601f19167fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1028452828420935b818110610bc45750908460019594939210610bab575b505050811b017fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025561057a565b015160001960f88460031b161c19169055388080610b7e565b92936020600181928786015181550195019301610b68565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10290925291507f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d601f840160051c81019160208510610c63575b918f9291601f8695930160051c01905b818110610c535750610531565b9283558493508f92600101610c46565b9091508190610c36565b60248d634e487b7160e01b81526041600452fd5b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005538610456565b60048a7ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b90501538610403565b303b1591506103fb565b8991506103f1565b8780fd5b8580fd5b8280fd5b5060606003193601126101b857610d3a6126cf565b60243567ffffffffffffffff8111610d2157610d5a90369060040161283c565b9060443567ffffffffffffffff81116109d557610d7b90369060040161283c565b602460206001600160a01b0360075416604051928380927f946b30ef0000000000000000000000000000000000000000000000000000000082523260048301525afa908115611090578591611061575b508015611052575b1561102a57326001600160a01b031960065416176006556001600160a01b03821692610e0c846000526017602052604060002054151590565b1561100257610f16610f0d82519360426020850195862060405160208101917f510f376a801a09772ac2abbd61d60d4a60500adc79f9adc1fca2c043965eb6e983523260408301528a6060830152608082015260808152610e6e60a0826127fd565b519020610e796136da565b610e81613744565b6040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a08152610ed260c0826127fd565b51902090604051917f190100000000000000000000000000000000000000000000000000000000000083526002830152602282015220613459565b90929192613495565b6001600160a01b0380875416911603610fda57344710610fae5784610f6b93928192519034855af13d15610fa6573d91610f4f83612820565b92610f5d60405194856127fd565b83523d86602085013e613568565b507fdf42bfa876a741bbe542cf1a563269e1390bf03901b5d433a6e8afd6ee36dbfe8280a260016001600160a01b0319600654161760065580f35b606091613568565b6024857fcd78605900000000000000000000000000000000000000000000000000000000815230600452fd5b6004857fd2bac4ba000000000000000000000000000000000000000000000000000000008152fd5b6004857f8ee6bc31000000000000000000000000000000000000000000000000000000008152fd5b6004847f5e087564000000000000000000000000000000000000000000000000000000008152fd5b5061105c326128d6565b610dd3565b611083915060203d602011611089575b61107b81836127fd565b810190612883565b38610dcb565b503d611071565b6040513d87823e3d90fd5b50346101b857806003193601126101b857602065ffffffffffff60045460a01c16604051908152f35b50346101b85760206003193601126101b8576110de6126cf565b6001600160a01b03825416330361025a576110f881612a66565b6009549081810291818304149015171561111b5790612710610201920490612ef4565b602483634e487b7160e01b81526011600452fd5b50346101b857806003193601126101b85760206001600160a01b0360045416604051908152f35b50346101b857806003193601126101b857604051611173816127e0565b600b5460ff811615158252602082019060081c60ff1615158152600c5460408301908152600d546001600160a01b031660608401908152600e546001600160a01b031660808501908152600f546001600160a01b031660a086019081526010546001600160a01b031660c087019081526011546001600160a01b03169060e088019182526040519261120484612792565b6012549467ffffffffffffffff86168552602085019560401c65ffffffffffff16865260135496604086019788526040519861123f8a6127c4565b6014546001600160a01b03168a526015546001600160a01b03169a60208b019b8c526040519c5115158d5251151560208d01525160408c0152516001600160a01b031660608b0152516001600160a01b031660808a0152516001600160a01b031660a0890152516001600160a01b031660c0880152516001600160a01b031660e08701525167ffffffffffffffff166101008601525165ffffffffffff1661012085015251610140840152516001600160a01b0316610160830152516001600160a01b03166101808201526101a090f35b50346101b857806003193601126101b85760165461132d8161289b565b9161133b60405193846127fd565b818352601f1961134a8361289b565b01366020850137805b828110611374576040516020808252819061137090820187612755565b0390f35b6001600160a01b036113858261328c565b90549060031b1c1684518210156113a957600582901b850160200152600101611353565b602483634e487b7160e01b81526032600452fd5b50346101b857806003193601126101b85760206001600160a01b0360075416604051908152f35b50346101b857806003193601126101b85760206001600160a01b0360025416604051908152f35b50346101b85760206003193601126101b8576114256126cf565b6001600160a01b038116808352600a602052604083209182549060ff8260a81c166118fa576003546040517f220d32d40000000000000000000000000000000000000000000000000000000081526001600160a01b03928316600482015292821660248401819052929160209183916044918391165afa9081156110905785916118db575b50156118b357600460208592604051928380927fce9b79300000000000000000000000000000000000000000000000000000000082525afa801561169a57829061186f575b6001600160a01b039150166bffffffffffffffffffffffff1980835460601b16166040517f3eb22c0f000000000000000000000000000000000000000000000000000000008152816004820152602081602481865afa801561177d57849061183b575b6000199150036117cd575b50600460206001600160a01b03865416604051928380927fbfefcd7b0000000000000000000000000000000000000000000000000000000082525afa9081156117c2578391611788575b50600854116116a557815460601b6bffffffffffffffffffffffff1916813b15610d215782916064839260405194859384927f020cf0c2000000000000000000000000000000000000000000000000000000008452600484015288602484015260001960448401525af1801561169a57611685575b505081740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff60019454161790557fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18380a380f35b8161168f916127fd565b610d2157823861161c565b6040513d84823e3d90fd5b815491939160601b6bffffffffffffffffffffffff1916813b156109d15784916064839260405194859384927f020cf0c200000000000000000000000000000000000000000000000000000000845260048401528860248401528160448401525af190811561177d578491611764575b50507fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff81541690557fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18280a380f35b8161176e916127fd565b611779578238611715565b5050fd5b6040513d86823e3d90fd5b9250506020823d6020116117ba575b816117a4602093836127fd565b810103126117b557849151386115a7565b600080fd5b3d9150611797565b6040513d85823e3d90fd5b908092503b156109d157604051907f0214534800000000000000000000000000000000000000000000000000000000825260048201526000196024820152848160448183865af1801561109057611827575b90849161155d565b84611834919592956127fd565b923861181f565b506020813d602011611867575b81611855602093836127fd565b810103126109d5576000199051611552565b3d9150611848565b506020813d6020116118ab575b81611889602093836127fd565b810103126118a7576118a26001600160a01b03916128b3565b6114ef565b5080fd5b3d915061187c565b6004847f439536aa000000000000000000000000000000000000000000000000000000008152fd5b6118f4915060203d6020116110895761107b81836127fd565b386114aa565b6004857f23daf16a000000000000000000000000000000000000000000000000000000008152fd5b50346101b85760206003193601126101b85760206001600160a01b0361194960043561328c565b90549060031b1c16604051908152f35b50346101b857806003193601126101b85760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b50346101b857806003193601126101b8576001600160a01b036020915416604051908152f35b50346101b857806003193601126101b8577fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100541580611b27575b15611ac957611a6d90611a10612d0a565b90611a19612e1f565b906020611a7b60405193611a2d83866127fd565b838552833681376040519687967f0f00000000000000000000000000000000000000000000000000000000000000885260e08589015260e0880190612714565b908682036040880152612714565b904660608601523060808601528260a086015284820360c08601528080855193848152019401925b828110611ab257505050500390f35b835185528695509381019392810192600101611aa3565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4549503731323a20556e696e697469616c697a656400000000000000000000006044820152fd5b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10154156119ff565b50346101b857806003193601126101b85760206001600160a01b0360065416604051908152f35b50346101b857806003193601126101b85760206001600160a01b0360015416604051908152f35b50346101b857806003193601126101b857611bb7612c6f565b806001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101b85760206003193601126101b85760406060916001600160a01b03611c5e6126cf565b168152600a602052205460ff604051916001600160a01b0381168352818160a01c161515602084015260a81c1615156040820152f35b50346101b857806003193601126101b8576020600954604051908152f35b50346101b8576001600160a01b03611cc9366126e5565b611cd4929192612c6f565b8015611d1257611ce58284166133bc565b505b151591167f5843bb05b84b2214eccaba0184a247ce2d47dba5292382aa88eb70a55522173a8380a380f35b611d1d8284166132d5565b50611ce7565b50346101b85760206003193601126101b857611d3d6126cf565b611d45612c6f565b6001600160a01b03196001600160a01b03600754921691826001600160a01b0382167f7fcf72baecc3134a31915febb8df705e0551f38069d9cb26de2c0da33b7a86978680a3161760075580f35b50346101b857806003193601126101b8576020601654604051908152f35b50346101b85760206003193601126101b857611dcb6126cf565b611dd3612c6f565b6001600160a01b038116808352600a6020526001600160a01b036040842054166124c657602460206001600160a01b0360015416604051928380927f14887c580000000000000000000000000000000000000000000000000000000082528660048301525afa90811561177d5784916124a7575b501561247f5760025483546040517f220d32d40000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201529084166024820181905293909160209183916044918391165afa90811561177d578491612460575b5015612438576001600160a01b0360055416916001600160a01b03600d54169260045491600b54600c546001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416936001600160a01b03600e54166001600160a01b03600f5416916001600160a01b0360105416936001600160a01b03601154169560405192610160840184811067ffffffffffffffff82111761242457604052808452602084019c8d5260408401908b60a01c65ffffffffffff168252606085019160ff841615158352608086019360081c60ff161515845260a0860194855260c08601958c875260e0810197885261010081019889526101208101998a5261014001998a526040519e8f926020840152516001600160a01b031660408301525165ffffffffffff16906060015251151560808d015251151560a08c01525160c08b0152516001600160a01b031660e08a0152516001600160a01b0316610100890152516001600160a01b0316610120880152516001600160a01b0316610140870152516001600160a01b0316610160860152610160855261205c610180866127fd565b6040519061206b6080836127fd565b60038252602082016060368237825115612410573090528151600110156123fc578260408301528151600210156123fc578161217a916060604094015261216c6001600160a01b0360155416916001600160a01b03601454168551936120d085612792565b8785526020850152858401528451926120e884612792565b835261213b602084018281528685019283526001600160a01b03875197889660208089015251828151168289015282602082015116606089015201511660808601525160a08086015260e0850190612755565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030160c0850152612755565b03601f1981018352826127fd565b60125467ffffffffffffffff81169190826123b5575060405161219e6020826127fd565b87815260003660208301375b604051926121b7846127e0565b60018452602084019485526040840197885260608401600281526080850193845260a08501936001855260c0860192835260e08601938452604051998a9788977fc48927e400000000000000000000000000000000000000000000000000000000895260048901602090525167ffffffffffffffff166024890152516001600160a01b0316604488015251606487016101009052610124870161225991612714565b915167ffffffffffffffff16608487015251908581037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc0160a487015261229f91612714565b9251151560c48501525167ffffffffffffffff1660e484015251908281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc016101048401526122ee91612714565b03916001600160a01b03169181865a94606095f19182156117c257839261235f575b50808352600a6020526001600160a01b0360408420921691826001600160a01b03198254161790557f7f74cf9c79e65b11e373ad23da18f4a761fe28401a5a663bbd34ffc2633f5bab8380a380f35b9091506060813d6060116123ad575b8161237b606093836127fd565b81010312610d21576123a56040612391836128b3565b9261239e602082016128b3565b50016128b3565b509038612310565b3d915061236e565b65ffffffffffff9060401c1660135460206040516123d2816127c4565b83815201908152604051916020830152516040820152604081526123f76060826127fd565b6121aa565b602487634e487b7160e01b81526032600452fd5b602488634e487b7160e01b81526032600452fd5b60248f634e487b7160e01b81526041600452fd5b6004837f424e73c5000000000000000000000000000000000000000000000000000000008152fd5b612479915060203d6020116110895761107b81836127fd565b38611eb0565b6004837f7c214f04000000000000000000000000000000000000000000000000000000008152fd5b6124c0915060203d6020116110895761107b81836127fd565b38611e47565b6004837f7dc7d19c000000000000000000000000000000000000000000000000000000008152fd5b50346101b857806003193601126101b85760206001600160a01b0360055416604051908152f35b50346101b857806003193601126101b85760206001600160a01b0360035416604051908152f35b50346101b85760206003193601126101b85760206102d26001600160a01b036125636126cf565b166000526017602052604060002054151590565b50346101b8576001600160a01b0361258e366126e5565b9190612598612c6f565b1690818352600a602052604083208160001461267057805460ff8160a81c16612648577fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff16750100000000000000000000000000000000000000000017905582827fdd292d3072309a5dc85b9e0ecffeba5719c5012fd6a01699c953680613fec6f18280a35b1515907f064709432483b7469e36cc282db9aa95ee5df7d163c25983d72758f36d89227a8380a380f35b6004857f1996476b000000000000000000000000000000000000000000000000000000008152fd5b805460ff8160a81c16156126a7577fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16905561261e565b6004857ff4ef2b3f000000000000000000000000000000000000000000000000000000008152fd5b600435906001600160a01b03821682036117b557565b60031960409101126117b5576004356001600160a01b03811681036117b5579060243580151581036117b55790565b919082519283825260005b848110612740575050601f19601f8460006020809697860101520116010190565b8060208092840101518282860101520161271f565b906020808351928381520192019060005b8181106127735750505090565b82516001600160a01b0316845260209384019390920191600101612766565b6060810190811067ffffffffffffffff8211176127ae57604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176127ae57604052565b610100810190811067ffffffffffffffff8211176127ae57604052565b90601f601f19910116810190811067ffffffffffffffff8211176127ae57604052565b67ffffffffffffffff81116127ae57601f01601f191660200190565b81601f820112156117b55780359061285382612820565b9261286160405194856127fd565b828452602083830101116117b557816000926020809301838601378301015290565b908160209103126117b5575180151581036117b55790565b67ffffffffffffffff81116127ae5760051b60200190565b51906001600160a01b03821682036117b557565b908160209103126117b5575190565b6001600160a01b038116600052600a6020526001600160a01b03604060002054168015612a3c576020600491604051928380927fce9b79300000000000000000000000000000000000000000000000000000000082525afa9081156129ee576000916129fa575b506000546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156129ee576000916129bc575b50600854111590565b90506020813d6020116129e6575b816129d7602093836127fd565b810103126117b55751386129b3565b3d91506129ca565b6040513d6000823e3d90fd5b90506020813d602011612a34575b81612a15602093836127fd565b810103126117b55761299f91612a2c6020926128b3565b91509161293d565b3d9150612a08565b7fae2411a60000000000000000000000000000000000000000000000000000000060005260046000fd5b6001600160a01b038116600052600a602052600460206001600160a01b0360406000205416604051928380927fce9b79300000000000000000000000000000000000000000000000000000000082525afa9081156129ee57600091612b6e575b506000546040517ffd4d447c00000000000000000000000000000000000000000000000000000000815260609190911b6bffffffffffffffffffffffff191660048201526001600160a01b039283166024820152916020918391829081604481015b0392165afa9081156129ee57600091612b3f575090565b90506020813d602011612b66575b81612b5a602093836127fd565b810103126117b5575190565b3d9150612b4d565b90506020813d602011612ba8575b81612b89602093836127fd565b810103126117b557612b2891612ba06020926128b3565b915091612ac6565b3d9150612b7c565b6001600160a01b03168015612c40576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b7f1e4fbdf700000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303612ca257565b7f118cdaa7000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b90600182811c92168015612d00575b6020831014612cea57565b634e487b7160e01b600052602260045260246000fd5b91607f1691612cdf565b604051906000827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1025491612d3d83612cd0565b8083529260018116908115612de25750600114612d63575b612d61925003836127fd565b565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102600090815290917f42ad5d3e1f2e6e70edcf6d991b8a3023d3fca8047a131592f9edb9fd9b89d57d5b818310612dc6575050906020612d6192820101612d55565b6020919350806001915483858901015201910190918492612dae565b60209250612d619491507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001682840152151560051b820101612d55565b604051906000827fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1035491612e5283612cd0565b8083529260018116908115612de25750600114612e7557612d61925003836127fd565b507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d103600090815290917f5f9ce34815f8e11431c7bb75a8e6886a91478f7ffc1dbb0a98dc240fddd76b755b818310612ed8575050906020612d6192820101612d55565b6020919350806001915483858901015201910190918492612ec0565b90612efe82612a66565b818110613262576001600160a01b0383169283600052600a6020526001600160a01b036040600020541660001942014281116130dd5765ffffffffffff1690600460206bffffffffffffffffffffffff198060005460601b161692604051928380927fb13442710000000000000000000000000000000000000000000000000000000082525afa80156129ee57600090613222575b6001600160a01b039150166040517fbb24fe8a000000000000000000000000000000000000000000000000000000008152602081600481855afa9081156129ee576000916131d7575b5067ffffffffffffffff169060028210156131ad57600094879261312157602095869461305260405161300f88826127fd565b838152601f1988013689830137604051988997889687957f021a81560000000000000000000000000000000000000000000000000000000087526004870161341c565b03925af180156129ee576130f3575b50505b8181039081116130dd577f4ed05e9673c26d2ed44f7ef6a7f2942df0ee3b5e1e17db4b99f9dcd261a339cd91602091600854116130a5575b604051908152a2565b83600052600a825260406000207fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff815416905561309c565b634e487b7160e01b600052601160045260246000fd5b8161311292903d1061311a575b61310a81836127fd565b8101906128c7565b503880613061565b503d613100565b602095869461317960405161313688826127fd565b838152601f1988013689830137604051988997889687957f545ce3890000000000000000000000000000000000000000000000000000000087526004870161341c565b03925af180156129ee5761318f575b5050613064565b816131a592903d1061311a5761310a81836127fd565b503880613188565b7fa739d4e20000000000000000000000000000000000000000000000000000000060005260046000fd5b6020813d60201161321a575b816131f0602093836127fd565b810103126118a757519067ffffffffffffffff821682036101b8575067ffffffffffffffff612fdc565b3d91506131e3565b506020813d60201161325a575b8161323c602093836127fd565b810103126117b5576132556001600160a01b03916128b3565b612f93565b3d915061322f565b7f8cc309fd0000000000000000000000000000000000000000000000000000000060005260046000fd5b6016548110156132a757601660005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b80548210156132a75760005260206000200190600090565b60008181526017602052604090205480156133b55760001981018181116130dd576016549060001982019182116130dd57818103613364575b505050601654801561334e57600019016133298160166132bd565b60001982549160031b1b19169055601655600052601760205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61339d6133756133869360166132bd565b90549060031b1c92839260166132bd565b81939154906000199060031b92831b921b19161790565b9055600052601760205260406000205538808061330e565b5050600090565b8060005260176020526040600020541560001461341657601654680100000000000000008110156127ae576133fd61338682600185940160165560166132bd565b9055601654906000526017602052604060002055600190565b50600090565b919360a0936001600160a01b03613456979665ffffffffffff94865216602085015260408401521660608201528160808201520190612714565b90565b815191906041830361348a5761348392506020820151906060604084015193015160001a90613651565b9192909190565b505060009160029190565b919091600481101561355257806134ab57509050565b6000600182036134df577ff645eedf0000000000000000000000000000000000000000000000000000000060005260046000fd5b506002810361351657827ffce698f70000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9091600360009214613526575050565b602492507fd78bce0c000000000000000000000000000000000000000000000000000000008252600452fd5b634e487b7160e01b600052602160045260246000fd5b906135a7575080511561357d57805190602001fd5b7f1425ea420000000000000000000000000000000000000000000000000000000060005260046000fd5b815115806135ef575b6135b8575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b50803b156135b0565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561362757565b7fd7e6bcf80000000000000000000000000000000000000000000000000000000060005260046000fd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116136ce579160209360809260ff60009560405194855216868401526040830152606082015282805260015afa156129ee576000516001600160a01b038116156136c25790600090600090565b50600090600190600090565b50505060009160039190565b6136e2612d0a565b80519081156136f2576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10054801561371f5790565b507fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47090565b61374c612e1f565b805190811561375c576020012090565b50507fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10154801561371f579056fea2646970667358221220ad886350c6210110bf4f2dee90f26905a8b1bdaf8d47836e098d09a0fba3102164736f6c634300081b0033
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.