Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 31 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Register Operato... | 3152016 | 3 hrs ago | IN | 0 ETH | 0.00009596 | ||||
Register Operato... | 3113653 | 5 days ago | IN | 0 ETH | 0.00000023 | ||||
Register Operato... | 3090793 | 9 days ago | IN | 0 ETH | 0.00000025 | ||||
Register Operato... | 3080572 | 10 days ago | IN | 0 ETH | 0.00000531 | ||||
Register Operato... | 3080529 | 10 days ago | IN | 0 ETH | 0.00006697 | ||||
Register Operato... | 3080522 | 10 days ago | IN | 0 ETH | 0.00005839 | ||||
Register Operato... | 3080456 | 10 days ago | IN | 0 ETH | 0.00005923 | ||||
Register Operato... | 3080443 | 10 days ago | IN | 0 ETH | 0.00005154 | ||||
Register Operato... | 3070859 | 12 days ago | IN | 0 ETH | 0.0000327 | ||||
Register Operato... | 3070815 | 12 days ago | IN | 0 ETH | 0.00032709 | ||||
Register Operato... | 3048885 | 15 days ago | IN | 0 ETH | 0.00000093 | ||||
Register Operato... | 3048833 | 15 days ago | IN | 0 ETH | 0.00021539 | ||||
Register Operato... | 3048564 | 15 days ago | IN | 0 ETH | 0.00000025 | ||||
Register Operato... | 3047027 | 15 days ago | IN | 0 ETH | 0.00000077 | ||||
Register Operato... | 3047007 | 15 days ago | IN | 0 ETH | 0.00000439 | ||||
Register Operato... | 3044958 | 15 days ago | IN | 0 ETH | 0.00004423 | ||||
Register Operato... | 3040371 | 16 days ago | IN | 0 ETH | 0.00002627 | ||||
Register Operato... | 3021655 | 19 days ago | IN | 0 ETH | 0.00007189 | ||||
Register Operato... | 3021535 | 19 days ago | IN | 0 ETH | 0.00001769 | ||||
Register Operato... | 3020452 | 19 days ago | IN | 0 ETH | 0.0000122 | ||||
Register Operato... | 3020408 | 19 days ago | IN | 0 ETH | 0.00001258 | ||||
Complete Task | 2961367 | 28 days ago | IN | 0 ETH | 0.00000005 | ||||
Create Task | 2961309 | 28 days ago | IN | 0 ETH | 0.00000014 | ||||
Register Operato... | 2961258 | 28 days ago | IN | 0 ETH | 0.0000003 | ||||
Register Operato... | 2961173 | 28 days ago | IN | 0 ETH | 0.00000003 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
SelfRegisterSqrtTaskMiddleware
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {INetworkRegistry} from "@symbiotic/interfaces/INetworkRegistry.sol"; import {IVault} from "@symbiotic/interfaces/vault/IVault.sol"; import {IBaseDelegator} from "@symbiotic/interfaces/delegator/IBaseDelegator.sol"; import {Subnetwork} from "@symbiotic/contracts/libraries/Subnetwork.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import {AccessManager} from "../../managers/extendable/AccessManager.sol"; import {BaseMiddleware} from "../../middleware/BaseMiddleware.sol"; import {SharedVaults} from "../../extensions/SharedVaults.sol"; import {SelfRegisterOperators} from "../../extensions/operators/SelfRegisterOperators.sol"; import {ECDSASig} from "../../extensions/managers/sigs/ECDSASig.sol"; import {OwnableAccessManager} from "../../extensions/managers/access/OwnableAccessManager.sol"; import {KeyManagerAddress} from "../../extensions/managers/keys/KeyManagerAddress.sol"; import {TimestampCapture} from "../../extensions/managers/capture-timestamps/TimestampCapture.sol"; import {EqualStakePower} from "../../extensions/managers/stake-powers/EqualStakePower.sol"; /** * @title SelfRegisterSqrtTaskMiddleware * @notice Middleware for managing sqrt computation tasks with self-registering operators * @dev Uses SelfRegisterOperators for operator management because it allows permissionless registration. * Task validation is done by a single validator chosen at task creation time because this avoids * having to iterate over all operators, making it more gas efficient and avoiding potential DOS attacks. */ contract SelfRegisterSqrtTaskMiddleware is SharedVaults, SelfRegisterOperators, ECDSASig, KeyManagerAddress, OwnableAccessManager, TimestampCapture, EqualStakePower { using Subnetwork for address; using Math for uint256; error InvalidHints(); error TaskCompleted(); error TooManyOperatorVaults(); error InactiveValidator(); event CreateTask(uint256 indexed taskIndex, address indexed validator); event CompleteTask(uint256 indexed taskIndex, bool isValidAnswer); struct Task { uint48 captureTimestamp; uint256 value; address validator; bool completed; } bytes32 private constant COMPLETE_TASK_TYPEHASH = keccak256("CompleteTask(uint256 taskIndex,uint256 answer)"); uint256 public constant MAX_OPERATOR_VAULTS = 20; Task[] public tasks; constructor( address networkRegistry, uint48 slashingWindow, address operatorRegistry, address vaultRegistry, address operatorNetOptin, address reader, address owner ) { initialize(networkRegistry, slashingWindow, vaultRegistry, operatorRegistry, operatorNetOptin, reader, owner); } function initialize( address networkRegistry, uint48 slashingWindow, address vaultRegistry, address operatorRegistry, address operatorNetOptin, address reader, address owner ) internal initializer { INetworkRegistry(networkRegistry).registerNetwork(); __BaseMiddleware_init(address(this), slashingWindow, vaultRegistry, operatorRegistry, operatorNetOptin, reader); __OwnableAccessManager_init(owner); __SelfRegisterOperators_init("SelfRegisterSqrtTaskMiddleware"); } function createTask(uint256 value, address validator) external returns (uint256 taskIndex) { bytes memory key = abi.encode(validator); address operator = operatorByKey(key); if (!keyWasActiveAt(getCaptureTimestamp(), key)) { revert InactiveValidator(); } if (!_isOperatorRegistered(operator)) { revert OperatorNotRegistered(); } taskIndex = tasks.length; tasks.push( Task({captureTimestamp: getCaptureTimestamp(), value: value, validator: validator, completed: false}) ); emit CreateTask(taskIndex, validator); } function completeTask( uint256 taskIndex, uint256 answer, bytes calldata signature, bytes[] calldata stakeHints, bytes[] calldata slashHints ) external returns (bool isValidAnswer) { isValidAnswer = _verify(taskIndex, answer, signature); tasks[taskIndex].completed = true; if (!isValidAnswer) { _slash(taskIndex, stakeHints, slashHints); } emit CompleteTask(taskIndex, isValidAnswer); } function _verify(uint256 taskIndex, uint256 answer, bytes calldata signature) private view returns (bool) { if (tasks[taskIndex].completed) { revert TaskCompleted(); } _verifySignature(taskIndex, answer, signature); return _verifyAnswer(taskIndex, answer); } function _verifySignature(uint256 taskIndex, uint256 answer, bytes calldata signature) private view { Task storage task = tasks[taskIndex]; bytes32 hash_ = _hashTypedDataV4(keccak256(abi.encode(COMPLETE_TASK_TYPEHASH, taskIndex, answer))); if (!SignatureChecker.isValidSignatureNow(task.validator, hash_, signature)) { revert InvalidSignature(); } } function _verifyAnswer(uint256 taskIndex, uint256 answer) private view returns (bool) { uint256 value = tasks[taskIndex].value; uint256 square = answer ** 2; if (square == value) { return true; } if (square < value) { uint256 difference = value - square; uint256 nextSquare = (answer + 1) ** 2; uint256 nextDifference = nextSquare > value ? nextSquare - value : value - nextSquare; if (difference <= nextDifference) { return true; } } else { uint256 difference = square - value; uint256 prevSquare = (answer - 1) ** 2; uint256 prevDifference = prevSquare > value ? prevSquare - value : value - prevSquare; if (difference <= prevDifference) { return true; } } return false; } function _slash(uint256 taskIndex, bytes[] calldata stakeHints, bytes[] calldata slashHints) private { Task storage task = tasks[taskIndex]; address operator = operatorByKey(abi.encode(task.validator)); _slashOperator(task.captureTimestamp, operator, stakeHints, slashHints); } function _slashOperator( uint48 captureTimestamp, address operator, bytes[] calldata stakeHints, bytes[] calldata slashHints ) private { address[] memory vaults = _activeVaultsAt(captureTimestamp, operator); uint256 vaultsLength = vaults.length; if (stakeHints.length != slashHints.length || stakeHints.length != vaultsLength) { revert InvalidHints(); } bytes32 subnetwork = _NETWORK().subnetwork(0); for (uint256 i; i < vaultsLength; ++i) { address vault = vaults[i]; uint256 slashAmount = IBaseDelegator(IVault(vault).delegator()).stakeAt(subnetwork, operator, captureTimestamp, stakeHints[i]); if (slashAmount == 0) { continue; } _slashVault(captureTimestamp, vault, subnetwork, operator, slashAmount, slashHints[i]); } } function executeSlash( uint48 epochStart, address vault, bytes32 subnetwork, address operator, uint256 amount, bytes memory hints ) external checkAccess { _slashVault(epochStart, vault, subnetwork, operator, amount, hints); } function _beforeRegisterOperatorVault(address operator, address vault) internal override { super._beforeRegisterOperatorVault(operator, vault); if (_operatorVaultsLength(operator) >= MAX_OPERATOR_VAULTS) { revert TooManyOperatorVaults(); } IBaseDelegator(IVault(vault).delegator()).setMaxNetworkLimit(DEFAULT_SUBNETWORK, type(uint256).max); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IRegistry} from "./common/IRegistry.sol"; interface INetworkRegistry is IRegistry { error NetworkAlreadyRegistered(); /** * @notice Register the caller as a network. */ function registerNetwork() 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 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 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 happens. * @param amount amount of the collateral to slash * @param captureTimestamp time point when the stake was captured * @param slashedAmount real amount of the collateral slashed */ event OnSlash(uint256 amount, uint48 captureTimestamp, 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. * @param account account to get the slashable collateral for * @return total amount of the account's 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 real 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 amount amount to slash * @param captureTimestamp time point when the stake was captured * @return slashedAmount real amount of the collateral slashed * @dev Only the slasher can call this function. */ function onSlash(uint256 amount, uint48 captureTimestamp) external returns (uint256 slashedAmount); /** * @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; 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 happens. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param amount amount of the collateral to be slashed * @param captureTimestamp time point when the stake was captured */ event OnSlash(bytes32 indexed subnetwork, address indexed operator, uint256 amount, uint48 captureTimestamp); /** * @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 amount 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 amount, uint48 captureTimestamp, bytes calldata data ) external; }
// 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 // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) pragma solidity ^0.8.20; import {Panic} from "../Panic.sol"; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { 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 success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { 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 success flag (no division by zero). */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(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. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * 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²⁵⁶ and mod 2²⁵⁶ - 1, then use // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2²⁵⁶ + 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²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); } /////////////////////////////////////////////// // 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²⁵⁶ / 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²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. 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⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // 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²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, 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; } } /** * @dev 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) { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. * * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that * `a**(p-2)` is the modular multiplicative inverse of a in Fp. * * NOTE: this function does NOT check that `p` is a prime greater than `2`. */ function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { unchecked { return Math.modExp(a, p - 2, p); } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); assembly ("memory-safe") { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); assembly ("memory-safe") { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 x) internal pure returns (uint256 r) { // If value has upper 128 bits set, log2 result is at least 128 r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7; // If upper 64 bits of 128-bit half set, add 64 to result r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6; // If upper 32 bits of 64-bit half set, add 32 to result r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5; // If upper 16 bits of 32-bit half set, add 16 to result r |= SafeCast.toUint((x >> r) > 0xffff) << 4; // If upper 8 bits of 16-bit half set, add 8 to result r |= SafeCast.toUint((x >> r) > 0xff) << 3; // If upper 4 bits of 8-bit half set, add 4 to result r |= SafeCast.toUint((x >> r) > 0xf) << 2; // Shifts value right by the current result and use it as an index into this lookup table: // // | x (4 bits) | index | table[index] = MSB position | // |------------|---------|-----------------------------| // | 0000 | 0 | table[0] = 0 | // | 0001 | 1 | table[1] = 0 | // | 0010 | 2 | table[2] = 1 | // | 0011 | 3 | table[3] = 1 | // | 0100 | 4 | table[4] = 2 | // | 0101 | 5 | table[5] = 2 | // | 0110 | 6 | table[6] = 2 | // | 0111 | 7 | table[7] = 2 | // | 1000 | 8 | table[8] = 3 | // | 1001 | 9 | table[9] = 3 | // | 1010 | 10 | table[10] = 3 | // | 1011 | 11 | table[11] = 3 | // | 1100 | 12 | table[12] = 3 | // | 1101 | 13 | table[13] = 3 | // | 1110 | 14 | table[14] = 3 | // | 1111 | 15 | table[15] = 3 | // // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes. assembly ("memory-safe") { r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000)) } } /** * @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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } /** * @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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } /** * @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; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 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 + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } /** * @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.1.0) (utils/cryptography/SignatureChecker.sol) pragma solidity ^0.8.20; import {ECDSA} from "./ECDSA.sol"; import {IERC1271} from "../../interfaces/IERC1271.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC-1271 signatures from smart contract wallets like * Argent and Safe Wallet (previously Gnosis Safe). */ library SignatureChecker { /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC-1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) { if (signer.code.length == 0) { (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature); return err == ECDSA.RecoverError.NoError && recovered == signer; } else { return isValidERC1271SignatureNow(signer, hash, signature); } } /** * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated * against the signer smart contract using ERC-1271. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidERC1271SignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (bool success, bytes memory result) = signer.staticcall( abi.encodeCall(IERC1271.isValidSignature, (hash, signature)) ); return (success && result.length >= 32 && abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @title AccessManager * @notice Abstract contract for managing access control * @dev Provides a modifier and internal function for checking access permissions */ abstract contract AccessManager is Initializable { /** * @notice Modifier that checks access before executing a function * @dev Calls internal _checkAccess function and continues if allowed */ modifier checkAccess() { _checkAccess(); _; } /** * @notice Internal function to check if caller has required access * @dev Must be implemented by inheriting contracts */ function _checkAccess() internal virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {VaultManager} from "../managers/VaultManager.sol"; import {OperatorManager} from "../managers/OperatorManager.sol"; import {AccessManager} from "../managers/extendable/AccessManager.sol"; import {KeyManager} from "../managers/extendable/KeyManager.sol"; /** * @title BaseMiddleware * @notice Abstract base contract that combines core manager functionality for building middleware * @dev Inherits from VaultManager, OperatorManager, AccessManager, and KeyManager to provide: * - Vault management and registration * - Operator management and registration * - Access management * - Key management * * This contract serves as a foundation for building custom middleware by providing essential * management capabilities that can be extended with additional functionality. */ abstract contract BaseMiddleware is VaultManager, OperatorManager, AccessManager, KeyManager { // This constant aggregates changes of all not extendable managers uint64 public constant BaseMiddleware_VERSION = 1; // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.BaseMiddleware")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReaderStorageLocation = 0xfd87879bc98f37af7578af722aecfbe5843e5ad354da2d1e70cb5157c4ec8800; /** * @notice Initializes the BaseMiddleware contract with required dependencies and parameters * @dev This internal initialization function sets up core storage and manager components * @param network The address of the network contract * @param slashingWindow The duration of the slashing window in blocks * @param vaultRegistry The address of the vault registry contract * @param operatorRegistry The address of the operator registry contract * @param operatorNetOptin The address of the operator network opt-in contract * @param reader The address of the reader contract used for delegatecall */ function __BaseMiddleware_init( address network, uint48 slashingWindow, address vaultRegistry, address operatorRegistry, address operatorNetOptin, address reader ) internal onlyInitializing { __NetworkStorage_init_private(network); __SlashingWindowStorage_init_private(slashingWindow); __VaultManager_init_private(vaultRegistry); __OperatorManager_init_private(operatorRegistry, operatorNetOptin); assembly { sstore(ReaderStorageLocation, reader) } } /** * @notice The fallback function is used to implement getter functions by delegating calls to the BasemiddlewareReader contract * @dev This allows the BaseMiddleware to expose view functions defined in the BasemiddlewareReader without explicitly implementing them, * reducing code duplication and maintaining a single source of truth for read operations */ fallback() external { address reader_; assembly { reader_ := sload(ReaderStorageLocation) } (bool success, bytes memory returndata) = reader_.delegatecall(abi.encodePacked(msg.data, address(this))); if (!success) { assembly { revert(add(returndata, 0x20), mload(returndata)) } } assembly { return(add(returndata, 0x20), mload(returndata)) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {BaseMiddleware} from "../middleware/BaseMiddleware.sol"; import {ISharedVaults} from "../interfaces/extensions/ISharedVaults.sol"; /** * @title SharedVaults * @notice Contract for managing shared vaults that can be used by multiple operators * @dev Extends BaseMiddleware to provide access control for vault management functions */ abstract contract SharedVaults is BaseMiddleware, ISharedVaults { uint64 public constant SharedVaults_VERSION = 1; /** * @inheritdoc ISharedVaults */ function registerSharedVault( address sharedVault ) public checkAccess { _beforeRegisterSharedVault(sharedVault); _registerSharedVault(sharedVault); } /** * @inheritdoc ISharedVaults */ function pauseSharedVault( address sharedVault ) public checkAccess { _beforePauseSharedVault(sharedVault); _pauseSharedVault(sharedVault); } /** * @inheritdoc ISharedVaults */ function unpauseSharedVault( address sharedVault ) public checkAccess { _beforeUnpauseSharedVault(sharedVault); _unpauseSharedVault(sharedVault); } /** * @inheritdoc ISharedVaults */ function unregisterSharedVault( address sharedVault ) public checkAccess { _beforeUnregisterSharedVault(sharedVault); _unregisterSharedVault(sharedVault); } /** * @notice Hook called before registering a shared vault * @param sharedVault The vault address */ function _beforeRegisterSharedVault( address sharedVault ) internal virtual {} /** * @notice Hook called before pausing a shared vault * @param sharedVault The vault address */ function _beforePauseSharedVault( address sharedVault ) internal virtual {} /** * @notice Hook called before unpausing a shared vault * @param sharedVault The vault address */ function _beforeUnpauseSharedVault( address sharedVault ) internal virtual {} /** * @notice Hook called before unregistering a shared vault * @param sharedVault The vault address */ function _beforeUnregisterSharedVault( address sharedVault ) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {BaseOperators} from "./BaseOperators.sol"; import {SigManager} from "../../managers/extendable/SigManager.sol"; import {EIP712Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import {ISelfRegisterOperators} from "../../interfaces/extensions/operators/ISelfRegisterOperators.sol"; /** * @title SelfRegisterOperators * @notice Contract for self-registration and management of operators with signature verification * @dev Extends BaseMiddleware, SigManager, and EIP712Upgradeable to provide signature-based operator management * @dev CAUTION: If activeOperators functionality is needed, use ApprovalRegisterOperators instead to prevent DOS attacks */ abstract contract SelfRegisterOperators is BaseOperators, SigManager, EIP712Upgradeable, ISelfRegisterOperators { uint64 public constant SelfRegisterOperators_VERSION = 1; // EIP-712 TypeHash constants bytes32 internal constant REGISTER_OPERATOR_TYPEHASH = keccak256("RegisterOperator(address operator,bytes key,address vault,uint256 nonce)"); bytes32 private constant UNREGISTER_OPERATOR_TYPEHASH = keccak256("UnregisterOperator(address operator,uint256 nonce)"); bytes32 private constant PAUSE_OPERATOR_TYPEHASH = keccak256("PauseOperator(address operator,uint256 nonce)"); bytes32 private constant UNPAUSE_OPERATOR_TYPEHASH = keccak256("UnpauseOperator(address operator,uint256 nonce)"); bytes32 private constant UPDATE_OPERATOR_KEY_TYPEHASH = keccak256("UpdateOperatorKey(address operator,bytes key,uint256 nonce)"); bytes32 private constant REGISTER_OPERATOR_VAULT_TYPEHASH = keccak256("RegisterOperatorVault(address operator,address vault,uint256 nonce)"); bytes32 private constant UNREGISTER_OPERATOR_VAULT_TYPEHASH = keccak256("UnregisterOperatorVault(address operator,address vault,uint256 nonce)"); bytes32 private constant PAUSE_OPERATOR_VAULT_TYPEHASH = keccak256("PauseOperatorVault(address operator,address vault,uint256 nonce)"); bytes32 private constant UNPAUSE_OPERATOR_VAULT_TYPEHASH = keccak256("UnpauseOperatorVault(address operator,address vault,uint256 nonce)"); struct SelfRegisterOperatorsStorage { mapping(address => uint256) nonces; } // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.SelfRegisterOperators")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant SelfResgisterOperators_STORAGE_LOCATION = 0x7c1bcd600c3fcfbc53470fac03a90d5cf6aa7b77c3f1ed10e6c6bd4d192eaf00; function _getSelfRegisterOperatorsStorage() internal pure returns (SelfRegisterOperatorsStorage storage $) { bytes32 location = SelfResgisterOperators_STORAGE_LOCATION; assembly { $.slot := location } } function nonces( address operator ) public view returns (uint256) { return _getSelfRegisterOperatorsStorage().nonces[operator]; } /** * @notice Initializes the contract with EIP712 domain separator * @param name The name to use for the EIP712 domain separator */ function __SelfRegisterOperators_init( string memory name ) internal onlyInitializing { __EIP712_init(name, "1"); } /** * @inheritdoc ISelfRegisterOperators */ function registerOperator(bytes memory key, address vault, bytes memory signature) external virtual { _verifyKey(msg.sender, key, signature); _registerOperatorImpl(msg.sender, key, vault); } /** * @inheritdoc ISelfRegisterOperators */ function registerOperator( address operator, bytes memory key, address vault, bytes memory signature, bytes memory keySignature ) public virtual { _verifyKey(operator, key, keySignature); SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(REGISTER_OPERATOR_TYPEHASH, operator, keccak256(key), vault, $.nonces[operator]++)), signature ); _registerOperatorImpl(operator, key, vault); } /** * @inheritdoc ISelfRegisterOperators */ function unregisterOperator() external override { _unregisterOperatorImpl(msg.sender); } /** * @inheritdoc ISelfRegisterOperators */ function unregisterOperator(address operator, bytes memory signature) public { SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(UNREGISTER_OPERATOR_TYPEHASH, operator, $.nonces[operator]++)), signature ); _unregisterOperatorImpl(operator); } /** * @inheritdoc ISelfRegisterOperators */ function pauseOperator() external override { _pauseOperatorImpl(msg.sender); } /** * @inheritdoc ISelfRegisterOperators */ function pauseOperator(address operator, bytes memory signature) public { SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(PAUSE_OPERATOR_TYPEHASH, operator, $.nonces[operator]++)), signature ); _pauseOperatorImpl(operator); } /** * @inheritdoc ISelfRegisterOperators */ function unpauseOperator() external override { _unpauseOperatorImpl(msg.sender); } /** * @inheritdoc ISelfRegisterOperators */ function unpauseOperator(address operator, bytes memory signature) public { SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(UNPAUSE_OPERATOR_TYPEHASH, operator, $.nonces[operator]++)), signature ); _unpauseOperatorImpl(operator); } /** * @inheritdoc ISelfRegisterOperators */ function updateOperatorKey(bytes memory key, bytes memory signature) external override { _verifyKey(msg.sender, key, signature); _updateOperatorKeyImpl(msg.sender, key); } /** * @inheritdoc ISelfRegisterOperators */ function updateOperatorKey( address operator, bytes memory key, bytes memory signature, bytes memory keySignature ) public { _verifyKey(operator, key, keySignature); SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(UPDATE_OPERATOR_KEY_TYPEHASH, operator, keccak256(key), $.nonces[operator]++)), signature ); _updateOperatorKeyImpl(operator, key); } /** * @inheritdoc ISelfRegisterOperators */ function registerOperatorVault( address vault ) external override { _registerOperatorVaultImpl(msg.sender, vault); } /** * @inheritdoc ISelfRegisterOperators */ function registerOperatorVault(address operator, address vault, bytes memory signature) public { if (!_isOperatorRegistered(operator)) { revert OperatorNotRegistered(); } SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(REGISTER_OPERATOR_VAULT_TYPEHASH, operator, vault, $.nonces[operator]++)), signature ); _registerOperatorVaultImpl(operator, vault); } /** * @inheritdoc ISelfRegisterOperators */ function unregisterOperatorVault( address vault ) external override { _unregisterOperatorVaultImpl(msg.sender, vault); } /** * @inheritdoc ISelfRegisterOperators */ function unregisterOperatorVault(address operator, address vault, bytes memory signature) public { SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(UNREGISTER_OPERATOR_VAULT_TYPEHASH, operator, vault, $.nonces[operator]++)), signature ); _unregisterOperatorVaultImpl(operator, vault); } /** * @inheritdoc ISelfRegisterOperators */ function pauseOperatorVault( address vault ) external override { _pauseOperatorVaultImpl(msg.sender, vault); } /** * @inheritdoc ISelfRegisterOperators */ function pauseOperatorVault(address operator, address vault, bytes memory signature) public { SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(PAUSE_OPERATOR_VAULT_TYPEHASH, operator, vault, $.nonces[operator]++)), signature ); _pauseOperatorVaultImpl(operator, vault); } /** * @inheritdoc ISelfRegisterOperators */ function unpauseOperatorVault( address vault ) external override { _unpauseOperatorVaultImpl(msg.sender, vault); } /** * @inheritdoc ISelfRegisterOperators */ function unpauseOperatorVault(address operator, address vault, bytes memory signature) public { SelfRegisterOperatorsStorage storage $ = _getSelfRegisterOperatorsStorage(); _verifyEIP712( operator, keccak256(abi.encode(UNPAUSE_OPERATOR_VAULT_TYPEHASH, operator, vault, $.nonces[operator]++)), signature ); _unpauseOperatorVaultImpl(operator, vault); } /** * @notice Verifies a key signature * @param operator The address of the operator * @param key The public key to verify (zero key is allowed for deletion) * @param signature The signature to verify */ function _verifyKey(address operator, bytes memory key, bytes memory signature) internal { if (key.length != 0 && !_verifyKeySignature(operator, key, signature)) { revert InvalidSignature(); } } /** * @notice Verifies an EIP712 signature * @param operator The address of the operator * @param structHash The hash of the EIP712 struct * @param signature The signature to verify */ function _verifyEIP712(address operator, bytes32 structHash, bytes memory signature) internal view { if (!SignatureChecker.isValidSignatureNow(operator, _hashTypedDataV4(structHash), signature)) { revert InvalidSignature(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {SigManager} from "../../../managers/extendable/SigManager.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {IECDSASig} from "../../../interfaces/extensions/managers/sigs/IECDSASig.sol"; /** * @title ECDSASig * @notice Contract for verifying ECDSA signatures against operator keys * @dev Implements SigManager interface using OpenZeppelin's ECDSA library. Instead of using public keys directly, * this implementation uses Ethereum addresses derived from the public keys as operator keys. */ abstract contract ECDSASig is SigManager, IECDSASig { uint64 public constant ECDSASig_VERSION = 1; using ECDSA for bytes32; /** * @notice Verifies that a signature was created by the owner of a key * @param operator The address of the operator that owns the key * @param key_ The address derived from the public key, encoded as bytes * @param signature The ECDSA signature to verify * @return True if the signature was created by the key owner, false otherwise * @dev The key is expected to be a bytes32 that can be converted to an Ethereum address */ function _verifyKeySignature( address operator, bytes memory key_, bytes memory signature ) internal pure override returns (bool) { address key = abi.decode(key_, (address)); bytes32 hash = keccak256(abi.encodePacked(operator, key)); address signer = recover(hash, signature); return signer == key && signer != address(0); } /** * @inheritdoc IECDSASig */ function recover(bytes32 hash, bytes memory signature) public pure returns (address) { return hash.recover(signature); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {AccessManager} from "../../../managers/extendable/AccessManager.sol"; import {IOwnableAccessManager} from "../../../interfaces/extensions/managers/access/IOwnableAccessManager.sol"; /** * @title OwnableAccessManager * @notice A middleware extension that restricts access to a single owner address * @dev Implements AccessManager with owner-based access control */ abstract contract OwnableAccessManager is AccessManager, IOwnableAccessManager { uint64 public constant OwnableAccessManager_VERSION = 1; // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.OwnableAccessManager")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableAccessManagerStorageLocation = 0xcee92923a0c63eca6fc0402d78c9efde9f9f3dc73e6f9e14501bf734ed77f100; function _owner() private view returns (address owner_) { bytes32 location = OwnableAccessManagerStorageLocation; assembly { owner_ := sload(location) } } /** * @notice Initializes the contract with an owner address * @param owner_ The address to set as the owner */ function __OwnableAccessManager_init( address owner_ ) internal onlyInitializing { _setOwner(owner_); } function _setOwner( address owner_ ) private { if (owner_ == address(0)) { revert InvalidOwner(address(0)); } bytes32 location = OwnableAccessManagerStorageLocation; assembly { sstore(location, owner_) } } /** * @inheritdoc IOwnableAccessManager */ function owner() public view returns (address) { return _owner(); } /** * @notice Checks if the caller has access (is the owner) * @dev Reverts if the caller is not the owner */ function _checkAccess() internal view virtual override { if (msg.sender != _owner()) { revert OnlyOwnerCanCall(msg.sender); } } /** * @inheritdoc IOwnableAccessManager */ function setOwner( address owner_ ) public checkAccess { _setOwner(owner_); } /** * @inheritdoc IOwnableAccessManager */ function renounceOwnership() public virtual { _checkAccess(); _setOwner(address(0)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {KeyManager} from "../../../managers/extendable/KeyManager.sol"; import {PauseableEnumerableSet} from "../../../libraries/PauseableEnumerableSet.sol"; /** * @title KeyManagerAddress * @notice Manages storage and validation of operator keys using address values * @dev Extends KeyManager to provide key management functionality */ abstract contract KeyManagerAddress is KeyManager { uint64 public constant KeyManagerAddress_VERSION = 1; using PauseableEnumerableSet for PauseableEnumerableSet.AddressSet; error DuplicateKey(); error MaxDisabledKeysReached(); uint256 private constant MAX_DISABLED_KEYS = 1; struct KeyManagerAddressStorage { /// @notice Mapping from operator addresses to their keys mapping(address => PauseableEnumerableSet.AddressSet) _keys; /// @notice Mapping from keys to operator addresses mapping(address => address) _keyToOperator; } // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.KeyManagerAddress")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant KeyManagerAddressStorageLocation = 0x3da47716e6090d5a5545e03387f4dac112d37cd069a5573bb81de8579bd9dc00; function _getKeyManagerAddressStorage() internal pure returns (KeyManagerAddressStorage storage s) { bytes32 location = KeyManagerAddressStorageLocation; assembly { s.slot := location } } /** * @notice Gets the operator address associated with a key * @param key The key to lookup * @return The operator address that owns the key, or zero address if none */ function operatorByKey( bytes memory key ) public view override returns (address) { KeyManagerAddressStorage storage $ = _getKeyManagerAddressStorage(); return $._keyToOperator[abi.decode(key, (address))]; } /** * @notice Gets an operator's active key at the current capture timestamp * @param operator The operator address to lookup * @return The operator's active key encoded as bytes, or encoded zero bytes if none */ function operatorKey( address operator ) public view override returns (bytes memory) { KeyManagerAddressStorage storage $ = _getKeyManagerAddressStorage(); address[] memory active = $._keys[operator].getActive(getCaptureTimestamp()); if (active.length == 0) { return abi.encode(address(0)); } return abi.encode(active[0]); } /** * @notice Checks if a key was active at a specific timestamp * @param timestamp The timestamp to check * @param key_ The key to check * @return True if the key was active at the timestamp, false otherwise */ function keyWasActiveAt(uint48 timestamp, bytes memory key_) public view override returns (bool) { KeyManagerAddressStorage storage $ = _getKeyManagerAddressStorage(); address key = abi.decode(key_, (address)); return $._keys[$._keyToOperator[key]].wasActiveAt(timestamp, key); } /** * @notice Updates an operator's key * @dev Handles key rotation by disabling old key and registering new one * @param operator The operator address to update * @param key_ The new key to register, encoded as bytes */ function _updateKey(address operator, bytes memory key_) internal override { KeyManagerAddressStorage storage $ = _getKeyManagerAddressStorage(); address key = abi.decode(key_, (address)); uint48 timestamp = _now(); if ($._keyToOperator[key] != address(0)) { revert DuplicateKey(); } // check if we have reached the max number of disabled keys // this allow us to limit the number times we can change the key if (key != address(0) && $._keys[operator].length() > MAX_DISABLED_KEYS + 1) { revert MaxDisabledKeysReached(); } if ($._keys[operator].length() > 0) { // try to remove disabled keys address prevKey = address($._keys[operator].set.array[0].value); if ($._keys[operator].checkUnregister(timestamp, _SLASHING_WINDOW(), prevKey)) { $._keys[operator].unregister(timestamp, _SLASHING_WINDOW(), prevKey); delete $._keyToOperator[prevKey]; } else if ($._keys[operator].wasActiveAt(timestamp, prevKey)) { $._keys[operator].pause(timestamp, prevKey); } } if (key != address(0)) { // register the new key $._keys[operator].register(timestamp, key); $._keyToOperator[key] = operator; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {CaptureTimestampManager} from "../../../managers/extendable/CaptureTimestampManager.sol"; /** * @title TimestampCapture * @notice A middleware extension that captures timestamps by subtracting 1 second from current time * @dev Implements CaptureTimestampManager with a simple timestamp capture mechanism */ abstract contract TimestampCapture is CaptureTimestampManager { uint64 public constant TimestampCapture_VERSION = 1; /* * @notice Returns the current timestamp minus 1 second. * @return timestamp The current timestamp minus 1 second. */ function getCaptureTimestamp() public view override returns (uint48 timestamp) { return _now() - 1; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {StakePowerManager} from "../../../managers/extendable/StakePowerManager.sol"; /** * @title EqualStakePower * @notice Implementation of a 1:1 stake to power conversion * @dev Simply returns the stake amount as the power amount without any modifications */ abstract contract EqualStakePower is StakePowerManager { /** * @notice Converts stake amount to voting power using a 1:1 ratio * @param vault The vault address (unused in this implementation) * @param stake The stake amount * @return power The calculated voting power (equal to stake) */ function stakeToPower(address vault, uint256 stake) public pure override returns (uint256 power) { return stake; } }
// 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; 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 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); /** * @notice 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 active stake 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); }
// 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 // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. * * _Available since v5.1._ */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { assembly ("memory-safe") { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.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 recovered, RecoverError err, bytes32 errArg) { 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. assembly ("memory-safe") { 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[ERC-2098 short signatures] */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { 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 recovered, RecoverError err, bytes32 errArg) { // 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.1.0) (interfaces/IERC1271.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// 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 pragma solidity ^0.8.25; import {IVault} from "@symbiotic/interfaces/vault/IVault.sol"; import {IBaseDelegator} from "@symbiotic/interfaces/delegator/IBaseDelegator.sol"; import {IRegistry} from "@symbiotic/interfaces/common/IRegistry.sol"; import {IEntity} from "@symbiotic/interfaces/common/IEntity.sol"; import {IVetoSlasher} from "@symbiotic/interfaces/slasher/IVetoSlasher.sol"; import {Subnetwork} from "@symbiotic/contracts/libraries/Subnetwork.sol"; import {ISlasher} from "@symbiotic/interfaces/slasher/ISlasher.sol"; import {IOperatorSpecificDelegator} from "@symbiotic/interfaces/delegator/IOperatorSpecificDelegator.sol"; import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import {StakePowerManager} from "./extendable/StakePowerManager.sol"; import {CaptureTimestampManager} from "./extendable/CaptureTimestampManager.sol"; import {NetworkStorage} from "./storages/NetworkStorage.sol"; import {SlashingWindowStorage} from "./storages/SlashingWindowStorage.sol"; import {PauseableEnumerableSet} from "../libraries/PauseableEnumerableSet.sol"; /** * @title VaultManager * @notice Abstract contract for managing vaults and their relationships with operators and subnetworks * @dev Extends BaseManager and provides functionality for registering, pausing, and managing vaults */ abstract contract VaultManager is NetworkStorage, SlashingWindowStorage, CaptureTimestampManager, StakePowerManager { using EnumerableMap for EnumerableMap.AddressToUintMap; using EnumerableMap for EnumerableMap.AddressToAddressMap; using PauseableEnumerableSet for PauseableEnumerableSet.AddressSet; using PauseableEnumerableSet for PauseableEnumerableSet.Uint160Set; using Subnetwork for address; error NotVault(); error NotOperatorVault(); error VaultNotInitialized(); error VaultAlreadyRegistered(); error VaultEpochTooShort(); error InactiveVaultSlash(); error UnknownSlasherType(); error NonVetoSlasher(); error NoSlasher(); error TooOldTimestampSlash(); error NotOperatorSpecificVault(); /// @custom:storage-location erc7201:symbiotic.storage.VaultManager struct VaultManagerStorage { address _vaultRegistry; PauseableEnumerableSet.Uint160Set _subnetworks; PauseableEnumerableSet.AddressSet _sharedVaults; mapping(address => PauseableEnumerableSet.AddressSet) _operatorVaults; EnumerableMap.AddressToAddressMap _vaultOperator; } event InstantSlash(address vault, bytes32 subnetwork, uint256 amount); event VetoSlash(address vault, bytes32 subnetwork, uint256 index); enum SlasherType { INSTANT, // Instant slasher type VETO // Veto slasher type } enum DelegatorType { FULL_RESTAKE, NETWORK_RESTAKE, OPERATOR_SPECIFIC } // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.VaultManager")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant VaultManagerStorageLocation = 0x485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db00; /** * @notice Internal helper to access the VaultManager storage struct * @dev Uses assembly to load storage location from a constant slot * @return $ Storage pointer to the VaultManagerStorage struct */ function _getVaultManagerStorage() internal pure returns (VaultManagerStorage storage $) { assembly { $.slot := VaultManagerStorageLocation } } uint96 internal constant DEFAULT_SUBNETWORK = 0; /** * @notice Initializes the VaultManager with required parameters * @param vaultRegistry The address of the vault registry contract */ function __VaultManager_init_private( address vaultRegistry ) internal onlyInitializing { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._vaultRegistry = vaultRegistry; _registerSubnetwork(DEFAULT_SUBNETWORK); } /** * @notice Gets the address of the vault registry contract * @return The vault registry contract address */ function _VAULT_REGISTRY() internal view returns (address) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._vaultRegistry; } /** * @notice Gets the total number of registered subnetworks * @return uint256 The count of registered subnetworks */ function _subnetworksLength() internal view returns (uint256) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._subnetworks.length(); } /** * @notice Gets the subnetwork information at a specific index * @param pos The index position to query * @return uint160 The subnetwork address * @return uint48 The time when the subnetwork was enabled * @return uint48 The time when the subnetwork was disabled */ function _subnetworkWithTimesAt( uint256 pos ) internal view returns (uint160, uint48, uint48) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._subnetworks.at(pos); } /** * @notice Gets all currently active subnetworks * @return uint160[] Array of active subnetwork addresses */ function _activeSubnetworks() internal view returns (uint160[] memory) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._subnetworks.getActive(getCaptureTimestamp()); } /** * @notice Gets all subnetworks that were active at a specific timestamp * @param timestamp The timestamp to check * @return uint160[] Array of subnetwork addresses that were active at the timestamp */ function _activeSubnetworksAt( uint48 timestamp ) internal view returns (uint160[] memory) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._subnetworks.getActive(timestamp); } /** * @notice Checks if a subnetwork was active at a specific timestamp * @param timestamp The timestamp to check * @param subnetwork The subnetwork identifier * @return bool True if the subnetwork was active at the timestamp */ function _subnetworkWasActiveAt(uint48 timestamp, uint96 subnetwork) internal view returns (bool) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._subnetworks.wasActiveAt(timestamp, uint160(subnetwork)); } /** * @notice Gets the total number of shared vaults * @return uint256 The count of shared vaults */ function _sharedVaultsLength() internal view returns (uint256) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._sharedVaults.length(); } /** * @notice Gets the vault information at a specific index * @param pos The index position to query * @return address The vault address * @return uint48 The time when the vault was enabled * @return uint48 The time when the vault was disabled */ function _sharedVaultWithTimesAt( uint256 pos ) internal view returns (address, uint48, uint48) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._sharedVaults.at(pos); } /** * @notice Gets all currently active shared vaults * @return address[] Array of active shared vault addresses */ function _activeSharedVaults() internal view returns (address[] memory) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._sharedVaults.getActive(getCaptureTimestamp()); } /** * @notice Gets all shared vaults that were active at a specific timestamp * @param timestamp The timestamp to check * @return address[] Array of shared vault addresses that were active at the timestamp */ function _activeSharedVaultsAt( uint48 timestamp ) internal view returns (address[] memory) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._sharedVaults.getActive(timestamp); } /** * @notice Gets the number of vaults associated with an operator * @param operator The operator address to query * @return uint256 The count of vaults for the operator */ function _operatorVaultsLength( address operator ) internal view returns (uint256) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._operatorVaults[operator].length(); } /** * @notice Gets the vault information at a specific index for an operator * @param operator The operator address * @param pos The index position to query * @return address The vault address * @return uint48 The time when the vault was enabled * @return uint48 The time when the vault was disabled */ function _operatorVaultWithTimesAt(address operator, uint256 pos) internal view returns (address, uint48, uint48) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._operatorVaults[operator].at(pos); } /** * @notice Gets all currently active vaults for a specific operator * @param operator The operator address * @return address[] Array of active vault addresses */ function _activeOperatorVaults( address operator ) internal view returns (address[] memory) { return _activeOperatorVaultsAt(getCaptureTimestamp(), operator); } /** * @notice Gets all currently active vaults for a specific operator at a specific timestamp * @param timestamp The timestamp to check * @param operator The operator address * @return address[] Array of active vault addresses */ function _activeOperatorVaultsAt(uint48 timestamp, address operator) internal view returns (address[] memory) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._operatorVaults[operator].getActive(timestamp); } /** * @notice Gets all currently active vaults across all operators * @return address[] Array of all active vault addresses */ function _activeVaults() internal view returns (address[] memory) { return _activeVaultsAt(getCaptureTimestamp()); } /** * @notice Gets all vaults that were active at a specific timestamp * @param timestamp The timestamp to check * @return address[] Array of vault addresses that were active at the timestamp */ function _activeVaultsAt( uint48 timestamp ) internal view returns (address[] memory) { VaultManagerStorage storage $ = _getVaultManagerStorage(); address[] memory activeSharedVaults_ = $._sharedVaults.getActive(timestamp); uint256 len = activeSharedVaults_.length; uint256 operatorVaultsLen = $._vaultOperator.length(); address[] memory vaults = new address[](len + operatorVaultsLen); for (uint256 i; i < len; ++i) { vaults[i] = activeSharedVaults_[i]; } for (uint256 i; i < operatorVaultsLen; ++i) { (address vault, address operator) = $._vaultOperator.at(i); if ($._operatorVaults[operator].wasActiveAt(timestamp, vault)) { vaults[len++] = vault; } } assembly { mstore(vaults, len) } return vaults; } /** * @notice Gets all currently active vaults for a specific operator * @param operator The operator address * @return address[] Array of active vault addresses for the operator */ function _activeVaults( address operator ) internal view returns (address[] memory) { return _activeVaultsAt(getCaptureTimestamp(), operator); } /** * @notice Gets all vaults that were active for an operator at a specific timestamp * @param timestamp The timestamp to check * @param operator The operator address * @return address[] Array of vault addresses that were active at the timestamp */ function _activeVaultsAt(uint48 timestamp, address operator) internal view returns (address[] memory) { VaultManagerStorage storage $ = _getVaultManagerStorage(); address[] memory activeSharedVaults_ = $._sharedVaults.getActive(timestamp); address[] memory activeOperatorVaults_ = $._operatorVaults[operator].getActive(timestamp); uint256 activeSharedVaultsLen = activeSharedVaults_.length; uint256 activeOperatorVaultsLen = activeOperatorVaults_.length; address[] memory vaults = new address[](activeSharedVaultsLen + activeOperatorVaultsLen); for (uint256 i; i < activeSharedVaultsLen; ++i) { vaults[i] = activeSharedVaults_[i]; } for (uint256 i; i < activeOperatorVaultsLen; ++i) { vaults[activeSharedVaultsLen + i] = activeOperatorVaults_[i]; } return vaults; } /** * @notice Checks if a vault was active at a specific timestamp * @param timestamp The timestamp to check * @param operator The operator address * @param vault The vault address * @return bool True if the vault was active at the timestamp */ function _vaultWasActiveAt(uint48 timestamp, address operator, address vault) internal view returns (bool) { return _sharedVaultWasActiveAt(timestamp, vault) || _operatorVaultWasActiveAt(timestamp, operator, vault); } /** * @notice Checks if a shared vault was active at a specific timestamp * @param timestamp The timestamp to check * @param vault The vault address * @return bool True if the shared vault was active at the timestamp */ function _sharedVaultWasActiveAt(uint48 timestamp, address vault) internal view returns (bool) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._sharedVaults.wasActiveAt(timestamp, vault); } /** * @notice Checks if an operator vault was active at a specific timestamp * @param timestamp The timestamp to check * @param operator The operator address * @param vault The vault address * @return bool True if the operator vault was active at the timestamp */ function _operatorVaultWasActiveAt( uint48 timestamp, address operator, address vault ) internal view returns (bool) { VaultManagerStorage storage $ = _getVaultManagerStorage(); return $._operatorVaults[operator].wasActiveAt(timestamp, vault); } /** * @notice Gets the stake amount for an operator in a vault and subnetwork at a specific timestamp * @param timestamp The timestamp to check * @param operator The operator address * @param vault The vault address * @param subnetwork The subnetwork identifier * @return uint256 The stake amount at the timestamp */ function _getOperatorStakeAt( uint48 timestamp, address operator, address vault, uint96 subnetwork ) private view returns (uint256) { bytes32 subnetworkId = _NETWORK().subnetwork(subnetwork); return IBaseDelegator(IVault(vault).delegator()).stakeAt(subnetworkId, operator, timestamp, ""); } /** * @notice Gets the power amount for an operator in a vault and subnetwork * @param operator The operator address * @param vault The vault address * @param subnetwork The subnetwork identifier * @return uint256 The power amount */ function _getOperatorPower(address operator, address vault, uint96 subnetwork) internal view returns (uint256) { return _getOperatorPowerAt(getCaptureTimestamp(), operator, vault, subnetwork); } /** * @notice Gets the power amount for an operator in a vault and subnetwork at a specific timestamp * @param timestamp The timestamp to check * @param operator The operator address * @param vault The vault address * @param subnetwork The subnetwork identifier * @return uint256 The power amount at the timestamp */ function _getOperatorPowerAt( uint48 timestamp, address operator, address vault, uint96 subnetwork ) internal view returns (uint256) { uint256 stake = _getOperatorStakeAt(timestamp, operator, vault, subnetwork); return stakeToPower(vault, stake); } /** * @notice Gets the total power amount for an operator across all vaults and subnetworks * @param operator The operator address * @return power The total power amount */ function _getOperatorPower( address operator ) internal view returns (uint256 power) { return _getOperatorPowerAt(getCaptureTimestamp(), operator); } /** * @notice Gets the total power amount for an operator across all vaults and subnetworks at a specific timestamp * @param timestamp The timestamp to check * @param operator The operator address * @return power The total power amount at the timestamp */ function _getOperatorPowerAt(uint48 timestamp, address operator) internal view returns (uint256 power) { address[] memory vaults = _activeVaultsAt(timestamp, operator); uint160[] memory subnetworks = _activeSubnetworksAt(timestamp); return _getOperatorPower(operator, vaults, subnetworks); } /** * @notice Gets the total power amount for an operator across all vaults and subnetworks * @param operator The operator address * @param vaults The list of vault addresses * @param subnetworks The list of subnetwork identifiers * @return power The total power amount */ function _getOperatorPower( address operator, address[] memory vaults, uint160[] memory subnetworks ) internal view returns (uint256 power) { return _getOperatorPowerAt(getCaptureTimestamp(), operator, vaults, subnetworks); } /** * @notice Gets the total power amount for an operator across all vaults and subnetworks at a specific timestamp * @param timestamp The timestamp to check * @param operator The operator address * @param vaults The list of vault addresses * @param subnetworks The list of subnetwork identifiers * @return power The total power amount at the timestamp */ function _getOperatorPowerAt( uint48 timestamp, address operator, address[] memory vaults, uint160[] memory subnetworks ) internal view returns (uint256 power) { for (uint256 i; i < vaults.length; ++i) { address vault = vaults[i]; for (uint256 j; j < subnetworks.length; ++j) { power += _getOperatorPowerAt(timestamp, operator, vault, uint96(subnetworks[j])); } } return power; } /** * @notice Calculates the total power for a list of operators * @param operators Array of operator addresses * @return power The total power amount */ function _totalPower( address[] memory operators ) internal view returns (uint256 power) { for (uint256 i; i < operators.length; ++i) { power += _getOperatorPower(operators[i]); } return power; } /** * @notice Registers a new subnetwork * @param subnetwork The subnetwork identifier to register */ function _registerSubnetwork( uint96 subnetwork ) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._subnetworks.register(_now(), uint160(subnetwork)); } /** * @notice Pauses a subnetwork * @param subnetwork The subnetwork identifier to pause */ function _pauseSubnetwork( uint96 subnetwork ) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._subnetworks.pause(_now(), uint160(subnetwork)); } /** * @notice Unpauses a subnetwork * @param subnetwork The subnetwork identifier to unpause */ function _unpauseSubnetwork( uint96 subnetwork ) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._subnetworks.unpause(_now(), _SLASHING_WINDOW(), uint160(subnetwork)); } /** * @notice Unregisters a subnetwork * @param subnetwork The subnetwork identifier to unregister */ function _unregisterSubnetwork( uint96 subnetwork ) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._subnetworks.unregister(_now(), _SLASHING_WINDOW(), uint160(subnetwork)); } /** * @notice Registers a new shared vault * @param vault The vault address to register */ function _registerSharedVault( address vault ) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); _validateVault(vault); $._sharedVaults.register(_now(), vault); } /** * @notice Registers a new operator vault * @param operator The operator address * @param vault The vault address to register */ function _registerOperatorVault(address operator, address vault) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); _validateVault(vault); _validateOperatorVault(operator, vault); $._operatorVaults[operator].register(_now(), vault); $._vaultOperator.set(vault, operator); } /** * @notice Pauses a shared vault * @param vault The vault address to pause */ function _pauseSharedVault( address vault ) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._sharedVaults.pause(_now(), vault); } /** * @notice Unpauses a shared vault * @param vault The vault address to unpause */ function _unpauseSharedVault( address vault ) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._sharedVaults.unpause(_now(), _SLASHING_WINDOW(), vault); } /** * @notice Pauses an operator vault * @param operator The operator address * @param vault The vault address to pause */ function _pauseOperatorVault(address operator, address vault) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._operatorVaults[operator].pause(_now(), vault); } /** * @notice Unpauses an operator vault * @param operator The operator address * @param vault The vault address to unpause */ function _unpauseOperatorVault(address operator, address vault) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._operatorVaults[operator].unpause(_now(), _SLASHING_WINDOW(), vault); } /** * @notice Unregisters a shared vault * @param vault The vault address to unregister */ function _unregisterSharedVault( address vault ) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._sharedVaults.unregister(_now(), _SLASHING_WINDOW(), vault); } /** * @notice Unregisters an operator vault * @param operator The operator address * @param vault The vault address to unregister */ function _unregisterOperatorVault(address operator, address vault) internal { VaultManagerStorage storage $ = _getVaultManagerStorage(); $._operatorVaults[operator].unregister(_now(), _SLASHING_WINDOW(), vault); $._vaultOperator.remove(vault); } /** * @notice Slashes a vault based on provided conditions * @param timestamp The timestamp when the slash occurs * @param vault The vault address * @param subnetwork The subnetwork identifier * @param operator The operator to slash * @param amount The amount to slash * @param hints Additional data for the slasher * @return response index for veto slashing or amount for instant slashing */ function _slashVault( uint48 timestamp, address vault, bytes32 subnetwork, address operator, uint256 amount, bytes memory hints ) internal returns (uint256 response) { VaultManagerStorage storage $ = _getVaultManagerStorage(); if (!($._sharedVaults.contains(vault) || $._operatorVaults[operator].contains(vault))) { revert NotOperatorVault(); } if (!_vaultWasActiveAt(timestamp, operator, vault)) { revert InactiveVaultSlash(); } if (timestamp + _SLASHING_WINDOW() < _now()) { revert TooOldTimestampSlash(); } address slasher = IVault(vault).slasher(); if (slasher == address(0)) { revert NoSlasher(); } uint64 slasherType = IEntity(slasher).TYPE(); if (slasherType == uint64(SlasherType.INSTANT)) { response = ISlasher(slasher).slash(subnetwork, operator, amount, timestamp, hints); emit InstantSlash(vault, subnetwork, response); } else if (slasherType == uint64(SlasherType.VETO)) { response = IVetoSlasher(slasher).requestSlash(subnetwork, operator, amount, timestamp, hints); emit VetoSlash(vault, subnetwork, response); } else { revert UnknownSlasherType(); } } /** * @notice Executes a veto-based slash for a vault * @param vault The vault address * @param slashIndex The index of the slash to execute * @param hints Additional data for the veto slasher * @return slashedAmount The amount that was slashed */ function _executeSlash( address vault, uint256 slashIndex, bytes calldata hints ) internal returns (uint256 slashedAmount) { address slasher = IVault(vault).slasher(); uint64 slasherType = IEntity(slasher).TYPE(); if (slasherType != uint64(SlasherType.VETO)) { revert NonVetoSlasher(); } return IVetoSlasher(slasher).executeSlash(slashIndex, hints); } /** * @notice Validates if a vault is properly initialized and registered * @param vault The vault address to validate */ function _validateVault( address vault ) private view { VaultManagerStorage storage $ = _getVaultManagerStorage(); if (!IRegistry(_VAULT_REGISTRY()).isEntity(vault)) { revert NotVault(); } if (!IVault(vault).isInitialized()) { revert VaultNotInitialized(); } if ($._vaultOperator.contains(vault) || $._sharedVaults.contains(vault)) { revert VaultAlreadyRegistered(); } uint48 vaultEpoch = IVault(vault).epochDuration(); address slasher = IVault(vault).slasher(); if (slasher != address(0)) { uint64 slasherType = IEntity(slasher).TYPE(); if (slasherType == uint64(SlasherType.VETO)) { vaultEpoch -= IVetoSlasher(slasher).vetoDuration(); } else if (slasherType > uint64(SlasherType.VETO)) { revert UnknownSlasherType(); } } if (vaultEpoch < _SLASHING_WINDOW()) { revert VaultEpochTooShort(); } } function _validateOperatorVault(address operator, address vault) internal view { address delegator = IVault(vault).delegator(); if ( IEntity(delegator).TYPE() != uint64(DelegatorType.OPERATOR_SPECIFIC) || IOperatorSpecificDelegator(delegator).operator() != operator ) { revert NotOperatorSpecificVault(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {IRegistry} from "@symbiotic/interfaces/common/IRegistry.sol"; import {IOptInService} from "@symbiotic/interfaces/service/IOptInService.sol"; import {NetworkStorage} from "./storages/NetworkStorage.sol"; import {SlashingWindowStorage} from "./storages/SlashingWindowStorage.sol"; import {CaptureTimestampManager} from "./extendable/CaptureTimestampManager.sol"; import {PauseableEnumerableSet} from "../libraries/PauseableEnumerableSet.sol"; /** * @title OperatorManager * @notice Manages operator registration and validation for the protocol * @dev Inherits from NetworkStorage, SlashingWindowStorage, and CaptureTimestampManager * to provide operator management functionality with network awareness and time-based features */ abstract contract OperatorManager is NetworkStorage, SlashingWindowStorage, CaptureTimestampManager { using PauseableEnumerableSet for PauseableEnumerableSet.AddressSet; error NotOperator(); error OperatorNotOptedIn(); /// @custom:storage-location erc7201:symbiotic.storage.OperatorManager struct OperatorManagerStorage { address _operatorRegistry; // Address of the operator registry address _operatorNetOptin; // Address of the operator network opt-in service PauseableEnumerableSet.AddressSet _operators; } // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.OperatorManager")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OperatorManagerStorageLocation = 0x3b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e00; /** * @notice Gets the storage pointer for OperatorManager state * @return $ Storage pointer to OperatorManagerStorage struct */ function _getOperatorManagerStorage() internal pure returns (OperatorManagerStorage storage $) { assembly { $.slot := OperatorManagerStorageLocation } } /** * @notice Initializes the OperatorManager with required parameters * @param operatorRegistry The address of the operator registry contract * @param operatorNetOptin The address of the operator network opt-in service */ function __OperatorManager_init_private( address operatorRegistry, address operatorNetOptin ) internal onlyInitializing { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); $._operatorRegistry = operatorRegistry; $._operatorNetOptin = operatorNetOptin; } /** * @notice Gets the address of the operator registry contract * @return The operator registry contract address */ function _OPERATOR_REGISTRY() internal view returns (address) { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); return $._operatorRegistry; } /** * @notice Gets the address of the operator network opt-in service contract * @return The operator network opt-in service contract address */ function _OPERATOR_NET_OPTIN() internal view returns (address) { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); return $._operatorNetOptin; } /** * @notice Returns the total number of registered operators, including both active and inactive * @return The number of registered operators */ function _operatorsLength() internal view returns (uint256) { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); return $._operators.length(); } /** * @notice Returns the operator and their associated enabled and disabled times at a specific position * @param pos The index position in the operators array * @return The operator address * @return The enabled timestamp * @return The disabled timestamp */ function _operatorWithTimesAt( uint256 pos ) internal view returns (address, uint48, uint48) { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); return $._operators.at(pos); } /** * @notice Returns a list of active operators * @return Array of addresses representing the active operators */ function _activeOperators() internal view returns (address[] memory) { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); return $._operators.getActive(getCaptureTimestamp()); } /** * @notice Returns a list of active operators at a specific timestamp * @param timestamp The timestamp to check * @return Array of addresses representing the active operators at the timestamp */ function _activeOperatorsAt( uint48 timestamp ) internal view returns (address[] memory) { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); return $._operators.getActive(timestamp); } /** * @notice Checks if a given operator was active at a specified timestamp * @param timestamp The timestamp to check * @param operator The operator address to check * @return True if the operator was active at the timestamp, false otherwise */ function _operatorWasActiveAt(uint48 timestamp, address operator) internal view returns (bool) { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); return $._operators.wasActiveAt(timestamp, operator); } /** * @notice Checks if an operator is registered * @param operator The address of the operator to check * @return True if the operator is registered, false otherwise */ function _isOperatorRegistered( address operator ) internal view returns (bool) { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); return $._operators.contains(operator); } /** * @notice Registers a new operator * @param operator The address of the operator to register */ function _registerOperator( address operator ) internal { if (!IRegistry(_OPERATOR_REGISTRY()).isEntity(operator)) { revert NotOperator(); } if (!IOptInService(_OPERATOR_NET_OPTIN()).isOptedIn(operator, _NETWORK())) { revert OperatorNotOptedIn(); } OperatorManagerStorage storage $ = _getOperatorManagerStorage(); $._operators.register(_now(), operator); } /** * @notice Pauses a registered operator * @param operator The address of the operator to pause */ function _pauseOperator( address operator ) internal { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); $._operators.pause(_now(), operator); } /** * @notice Unpauses a paused operator * @param operator The address of the operator to unpause */ function _unpauseOperator( address operator ) internal { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); $._operators.unpause(_now(), _SLASHING_WINDOW(), operator); } /** * @notice Unregisters an operator * @param operator The address of the operator to unregister */ function _unregisterOperator( address operator ) internal { OperatorManagerStorage storage $ = _getOperatorManagerStorage(); $._operators.unregister(_now(), _SLASHING_WINDOW(), operator); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {SlashingWindowStorage} from "../storages/SlashingWindowStorage.sol"; import {CaptureTimestampManager} from "./CaptureTimestampManager.sol"; /** * @title KeyManager * @notice Abstract contract for managing keys */ abstract contract KeyManager is SlashingWindowStorage, CaptureTimestampManager { /** * @notice Updates the key associated with an operator * @param operator The address of the operator * @param key The key to update, or empty bytes to delete the key */ function _updateKey(address operator, bytes memory key) internal virtual; /** * @notice Returns the operator address associated with a given key * @param key The key for which to find the associated operator * @return The address of the operator linked to the specified key */ function operatorByKey( bytes memory key ) public view virtual returns (address); /** * @notice Returns the current or previous key for a given operator * @dev Returns the previous key if the key was updated in the current epoch * @param operator The address of the operator * @return The key associated with the specified operator */ function operatorKey( address operator ) public view virtual returns (bytes memory); /** * @notice Checks if a key was active at a specific timestamp * @param timestamp The timestamp to check * @param key The key to check * @return True if the key was active at the timestamp, false otherwise */ function keyWasActiveAt(uint48 timestamp, bytes memory key) public view virtual returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; /** * @title ISharedVaults * @notice Interface for managing shared vaults that can be used by multiple operators */ interface ISharedVaults { /** * @notice Registers a new shared vault * @param sharedVault The address of the vault to register */ function registerSharedVault( address sharedVault ) external; /** * @notice Pauses a shared vault * @param sharedVault The address of the vault to pause */ function pauseSharedVault( address sharedVault ) external; /** * @notice Unpauses a shared vault * @param sharedVault The address of the vault to unpause */ function unpauseSharedVault( address sharedVault ) external; /** * @notice Unregisters a shared vault * @param sharedVault The address of the vault to unregister */ function unregisterSharedVault( address sharedVault ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {BaseMiddleware} from "../../middleware/BaseMiddleware.sol"; /** * @title BaseOperators * @notice Base contract for managing operator registration, keys, and vault relationships * @dev Provides core operator management functionality with hooks for customization */ abstract contract BaseOperators is BaseMiddleware { error OperatorNotRegistered(); /** * @notice Internal implementation for registering an operator * @param operator The operator address to register * @param key The operator's public key * @param vault Optional vault address to associate with operator */ function _registerOperatorImpl(address operator, bytes memory key, address vault) internal virtual { _beforeRegisterOperator(operator, key, vault); _registerOperator(operator); _updateKey(operator, key); if (vault != address(0)) { _beforeRegisterOperatorVault(operator, vault); _registerOperatorVault(operator, vault); } } /** * @notice Internal implementation for unregistering an operator * @param operator The operator address to unregister */ function _unregisterOperatorImpl( address operator ) internal virtual { _beforeUnregisterOperator(operator); _unregisterOperator(operator); } /** * @notice Internal implementation for pausing an operator * @param operator The operator address to pause */ function _pauseOperatorImpl( address operator ) internal virtual { _beforePauseOperator(operator); _pauseOperator(operator); } /** * @notice Internal implementation for unpausing an operator * @param operator The operator address to unpause */ function _unpauseOperatorImpl( address operator ) internal virtual { _beforeUnpauseOperator(operator); _unpauseOperator(operator); } /** * @notice Internal implementation for updating an operator's key * @param operator The operator address * @param key The new public key */ function _updateOperatorKeyImpl(address operator, bytes memory key) internal virtual { _beforeUpdateOperatorKey(operator, key); _updateKey(operator, key); } /** * @notice Internal implementation for registering an operator-vault pair * @param operator The operator address * @param vault The vault address to associate * @dev Reverts if operator is not registered */ function _registerOperatorVaultImpl(address operator, address vault) internal virtual { if (!_isOperatorRegistered(operator)) { revert OperatorNotRegistered(); } _beforeRegisterOperatorVault(operator, vault); _registerOperatorVault(operator, vault); } /** * @notice Internal implementation for unregistering an operator-vault pair * @param operator The operator address * @param vault The vault address to unregister */ function _unregisterOperatorVaultImpl(address operator, address vault) internal virtual { _beforeUnregisterOperatorVault(operator, vault); _unregisterOperatorVault(operator, vault); } /** * @notice Internal implementation for pausing an operator-vault pair * @param operator The operator address * @param vault The vault address to pause */ function _pauseOperatorVaultImpl(address operator, address vault) internal virtual { _beforePauseOperatorVault(operator, vault); _pauseOperatorVault(operator, vault); } /** * @notice Internal implementation for unpausing an operator-vault pair * @param operator The operator address * @param vault The vault address to unpause */ function _unpauseOperatorVaultImpl(address operator, address vault) internal virtual { _beforeUnpauseOperatorVault(operator, vault); _unpauseOperatorVault(operator, vault); } /** * @notice Hook called before updating an operator's key * @param operator The operator address * @param key The new key */ function _beforeUpdateOperatorKey(address operator, bytes memory key) internal virtual {} /** * @notice Hook called before registering an operator * @param operator The operator address * @param key The operator's key * @param vault Optional vault address */ function _beforeRegisterOperator(address operator, bytes memory key, address vault) internal virtual {} /** * @notice Hook called before unregistering an operator * @param operator The operator address */ function _beforeUnregisterOperator( address operator ) internal virtual {} /** * @notice Hook called before pausing an operator * @param operator The operator address */ function _beforePauseOperator( address operator ) internal virtual {} /** * @notice Hook called before unpausing an operator * @param operator The operator address */ function _beforeUnpauseOperator( address operator ) internal virtual {} /** * @notice Hook called before registering an operator-vault pair * @param operator The operator address * @param vault The vault address */ function _beforeRegisterOperatorVault(address operator, address vault) internal virtual {} /** * @notice Hook called before unregistering an operator-vault pair * @param operator The operator address * @param vault The vault address */ function _beforeUnregisterOperatorVault(address operator, address vault) internal virtual {} /** * @notice Hook called before pausing an operator-vault pair * @param operator The operator address * @param vault The vault address */ function _beforePauseOperatorVault(address operator, address vault) internal virtual {} /** * @notice Hook called before unpausing an operator-vault pair * @param operator The operator address * @param vault The vault address */ function _beforeUnpauseOperatorVault(address operator, address vault) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @title SigManager * @notice Abstract contract for verifying signatures against operator keys * @dev Provides signature verification functionality for operator keys */ abstract contract SigManager is Initializable { /** * @notice Verifies that a signature was created by the owner of a key * @param operator The address of the operator that owns the key * @param key_ The public key to verify against * @param signature The signature to verify * @return True if the signature was created by the key owner, false otherwise */ function _verifyKeySignature( address operator, bytes memory key_, bytes memory signature ) internal virtual returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.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 pragma solidity ^0.8.25; /** * @title ISelfRegisterOperators * @notice Interface for self-registration and management of operators with signature verification */ interface ISelfRegisterOperators { error InvalidSignature(); /** * @notice Returns the nonce for an operator address * @param operator The operator address to check * @return The current nonce value */ function nonces( address operator ) external view returns (uint256); /** * @notice Allows an operator to self-register with a key and optional vault * @param key The operator's public key * @param vault Optional vault address to associate with the operator * @param signature Signature proving ownership of the key */ function registerOperator(bytes memory key, address vault, bytes memory signature) external; /** * @notice Registers an operator on behalf of another address with signature verification * @param operator The address of the operator to register * @param key The operator's public key * @param vault Optional vault address to associate * @param signature EIP712 signature authorizing registration * @param keySignature Signature proving ownership of the key */ function registerOperator( address operator, bytes memory key, address vault, bytes memory signature, bytes memory keySignature ) external; /** * @notice Allows an operator to unregister themselves */ function unregisterOperator() external; /** * @notice Unregisters an operator with signature verification * @param operator The address of the operator to unregister * @param signature EIP712 signature authorizing unregistration */ function unregisterOperator(address operator, bytes memory signature) external; /** * @notice Allows an operator to pause themselves */ function pauseOperator() external; /** * @notice Pauses an operator with signature verification * @param operator The address of the operator to pause * @param signature EIP712 signature authorizing pause */ function pauseOperator(address operator, bytes memory signature) external; /** * @notice Allows an operator to unpause themselves */ function unpauseOperator() external; /** * @notice Unpauses an operator with signature verification * @param operator The address of the operator to unpause * @param signature EIP712 signature authorizing unpause */ function unpauseOperator(address operator, bytes memory signature) external; /** * @notice Allows an operator to update their own key * @param key The new public key * @param signature Signature proving ownership of the key */ function updateOperatorKey(bytes memory key, bytes memory signature) external; /** * @notice Updates an operator's key with signature verification * @param operator The address of the operator * @param key The new public key * @param signature EIP712 signature authorizing key update * @param keySignature Signature proving ownership of the new key */ function updateOperatorKey( address operator, bytes memory key, bytes memory signature, bytes memory keySignature ) external; /** * @notice Allows an operator to register a vault association * @param vault The address of the vault to associate */ function registerOperatorVault( address vault ) external; /** * @notice Registers a vault association with signature verification * @param operator The address of the operator * @param vault The address of the vault * @param signature EIP712 signature authorizing vault registration */ function registerOperatorVault(address operator, address vault, bytes memory signature) external; /** * @notice Allows an operator to unregister a vault association * @param vault The address of the vault to unregister */ function unregisterOperatorVault( address vault ) external; /** * @notice Unregisters a vault association with signature verification * @param operator The address of the operator * @param vault The address of the vault * @param signature EIP712 signature authorizing vault unregistration */ function unregisterOperatorVault(address operator, address vault, bytes memory signature) external; /** * @notice Allows an operator to pause a vault association * @param vault The address of the vault to pause */ function pauseOperatorVault( address vault ) external; /** * @notice Pauses a vault association with signature verification * @param operator The address of the operator * @param vault The address of the vault * @param signature EIP712 signature authorizing vault pause */ function pauseOperatorVault(address operator, address vault, bytes memory signature) external; /** * @notice Allows an operator to unpause a vault association * @param vault The address of the vault to unpause */ function unpauseOperatorVault( address vault ) external; /** * @notice Unpauses a vault association with signature verification * @param operator The address of the operator * @param vault The address of the vault * @param signature EIP712 signature authorizing vault unpause */ function unpauseOperatorVault(address operator, address vault, bytes memory signature) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; /** * @title IECDSASig * @notice Interface for verifying ECDSA signatures against operator keys * @dev Extends ISigManager interface for ECDSA signature verification */ interface IECDSASig { /** * @notice Recovers the signer address from a hash and signature * @param hash The message hash that was signed * @param signature The ECDSA signature * @return The address that created the signature * @dev Wrapper around OpenZeppelin's ECDSA.recover */ function recover(bytes32 hash, bytes memory signature) external pure returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; /** * @title IOwnableAccessManager * @notice Interface for a middleware extension that restricts access to a single owner address */ interface IOwnableAccessManager { /** * @notice Error thrown when a non-owner address attempts to call a restricted function * @param sender The address that attempted the call */ error OnlyOwnerCanCall(address sender); /** * @notice Error thrown when trying to set an invalid owner address * @param owner The invalid owner address */ error InvalidOwner(address owner); /** * @notice Gets the current owner address * @return The owner address */ function owner() external view returns (address); /** * @notice Updates the owner address * @param owner_ The new owner address * @dev Can only be called by the current owner */ function setOwner( address owner_ ) external; /** * @notice Renounces the ownership of the contract * @dev Can only be called by the current owner */ function renounceOwnership() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; /** * @title PauseableEnumerableSet * @notice Library for managing sets of values that can be paused and unpaused * @dev Provides functionality for managing sets of addresses, uint160s, bytes32s and bytes values * Each value in a set has an associated status that tracks when it was enabled/disabled */ library PauseableEnumerableSet { using PauseableEnumerableSet for Inner160; using PauseableEnumerableSet for Uint160Set; using PauseableEnumerableSet for InnerBytes32; using PauseableEnumerableSet for InnerBytes; using PauseableEnumerableSet for Status; error AlreadyRegistered(); error NotRegistered(); error AlreadyEnabled(); error NotEnabled(); error Enabled(); error ImmutablePeriodNotPassed(); /** * @dev Stores the enabled and disabled timestamps for a value */ struct Status { uint48 enabled; uint48 disabled; } /** * @dev Stores a uint160 value and its status */ struct Inner160 { uint160 value; Status status; } /** * @dev Stores a bytes32 value and its status */ struct InnerBytes32 { bytes32 value; Status status; } /** * @dev Stores a bytes value and its status */ struct InnerBytes { bytes value; Status status; } /** * @dev Set of uint160 values with their statuses */ struct Uint160Set { Inner160[] array; mapping(uint160 => uint256) positions; } /** * @dev Set of address values, implemented using Uint160Set */ struct AddressSet { Uint160Set set; } /** * @dev Set of bytes32 values with their statuses */ struct Bytes32Set { InnerBytes32[] array; mapping(bytes32 => uint256) positions; } /** * @dev Set of bytes values with their statuses */ struct BytesSet { InnerBytes[] array; mapping(bytes => uint256) positions; } /** * @notice Sets the initial status of a value * @param self The status to modify * @param timestamp The timestamp to set as enabled */ function set(Status storage self, uint48 timestamp) internal { self.enabled = timestamp; self.disabled = 0; } /** * @notice Enables a previously disabled value * @param self The status to modify * @param timestamp The timestamp to set as enabled * @param immutablePeriod The required waiting period after disabling */ function enable(Status storage self, uint48 timestamp, uint48 immutablePeriod) internal { if (self.enabled != 0) revert AlreadyEnabled(); if (self.disabled + immutablePeriod > timestamp) revert ImmutablePeriodNotPassed(); self.enabled = timestamp; self.disabled = 0; } /** * @notice Disables an enabled value * @param self The status to modify * @param timestamp The timestamp to set as disabled */ function disable(Status storage self, uint48 timestamp) internal { if (self.disabled != 0) revert NotEnabled(); self.enabled = 0; self.disabled = timestamp; } /** * @notice Validates if a value can be unregistered * @param self The status to check * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling */ function validateUnregister(Status storage self, uint48 timestamp, uint48 immutablePeriod) internal view { if (self.enabled != 0 || self.disabled == 0) revert Enabled(); if (self.disabled + immutablePeriod > timestamp) revert ImmutablePeriodNotPassed(); } /** * @notice Checks if a value can be unregistered * @param self The status to check * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling * @return bool Whether the value can be unregistered */ function checkUnregister( Status storage self, uint48 timestamp, uint48 immutablePeriod ) internal view returns (bool) { return self.enabled == 0 && self.disabled != 0 && self.disabled + immutablePeriod <= timestamp; } /** * @notice Checks if a value was active at a given timestamp * @param self The status to check * @param timestamp The timestamp to check * @return bool Whether the value was active */ function wasActiveAt(Status storage self, uint48 timestamp) internal view returns (bool) { return self.enabled < timestamp && (self.disabled == 0 || self.disabled >= timestamp); } /** * @notice Gets the value and status for an Inner160 * @param self The Inner160 to get data from * @return The value, enabled timestamp, and disabled timestamp */ function get( Inner160 storage self ) internal view returns (uint160, uint48, uint48) { return (self.value, self.status.enabled, self.status.disabled); } /** * @notice Gets the value and status for an InnerBytes32 * @param self The InnerBytes32 to get data from * @return The value, enabled timestamp, and disabled timestamp */ function get( InnerBytes32 storage self ) internal view returns (bytes32, uint48, uint48) { return (self.value, self.status.enabled, self.status.disabled); } /** * @notice Gets the value and status for an InnerBytes * @param self The InnerBytes to get data from * @return The value, enabled timestamp, and disabled timestamp */ function get( InnerBytes storage self ) internal view returns (bytes memory, uint48, uint48) { return (self.value, self.status.enabled, self.status.disabled); } // AddressSet functions /** * @notice Gets the number of addresses in the set * @param self The AddressSet to query * @return uint256 The number of addresses */ function length( AddressSet storage self ) internal view returns (uint256) { return self.set.length(); } /** * @notice Gets the address and status at a given position * @param self The AddressSet to query * @param pos The position to query * @return The address, enabled timestamp, and disabled timestamp */ function at(AddressSet storage self, uint256 pos) internal view returns (address, uint48, uint48) { (uint160 value, uint48 enabled, uint48 disabled) = self.set.at(pos); return (address(value), enabled, disabled); } /** * @notice Gets all active addresses at a given timestamp * @param self The AddressSet to query * @param timestamp The timestamp to check * @return array Array of active addresses */ function getActive(AddressSet storage self, uint48 timestamp) internal view returns (address[] memory array) { uint160[] memory uint160Array = self.set.getActive(timestamp); assembly { array := uint160Array } return array; } /** * @notice Checks if an address was active at a given timestamp * @param self The AddressSet to query * @param timestamp The timestamp to check * @param addr The address to check * @return bool Whether the address was active */ function wasActiveAt(AddressSet storage self, uint48 timestamp, address addr) internal view returns (bool) { return self.set.wasActiveAt(timestamp, uint160(addr)); } /** * @notice Registers a new address * @param self The AddressSet to modify * @param timestamp The timestamp to set as enabled * @param addr The address to register */ function register(AddressSet storage self, uint48 timestamp, address addr) internal { self.set.register(timestamp, uint160(addr)); } /** * @notice Pauses an address * @param self The AddressSet to modify * @param timestamp The timestamp to set as disabled * @param addr The address to pause */ function pause(AddressSet storage self, uint48 timestamp, address addr) internal { self.set.pause(timestamp, uint160(addr)); } /** * @notice Unpauses an address * @param self The AddressSet to modify * @param timestamp The timestamp to set as enabled * @param immutablePeriod The required waiting period after disabling * @param addr The address to unpause */ function unpause(AddressSet storage self, uint48 timestamp, uint48 immutablePeriod, address addr) internal { self.set.unpause(timestamp, immutablePeriod, uint160(addr)); } /** * @notice Checks if an address can be unregistered * @param self The AddressSet to query * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling * @param value The address to check * @return bool Whether the address can be unregistered */ function checkUnregister( AddressSet storage self, uint48 timestamp, uint48 immutablePeriod, address value ) internal view returns (bool) { uint256 pos = self.set.positions[uint160(value)]; if (pos == 0) return false; return self.set.array[pos - 1].status.checkUnregister(timestamp, immutablePeriod); } /** * @notice Unregisters an address * @param self The AddressSet to modify * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling * @param addr The address to unregister */ function unregister(AddressSet storage self, uint48 timestamp, uint48 immutablePeriod, address addr) internal { self.set.unregister(timestamp, immutablePeriod, uint160(addr)); } /** * @notice Checks if an address is registered * @param self The AddressSet to query * @param addr The address to check * @return bool Whether the address is registered */ function contains(AddressSet storage self, address addr) internal view returns (bool) { return self.set.contains(uint160(addr)); } // Uint160Set functions /** * @notice Gets the number of uint160s in the set * @param self The Uint160Set to query * @return uint256 The number of uint160s */ function length( Uint160Set storage self ) internal view returns (uint256) { return self.array.length; } /** * @notice Gets the uint160 and status at a given position * @param self The Uint160Set to query * @param pos The position to query * @return The uint160, enabled timestamp, and disabled timestamp */ function at(Uint160Set storage self, uint256 pos) internal view returns (uint160, uint48, uint48) { return self.array[pos].get(); } /** * @notice Gets all active uint160s at a given timestamp * @param self The Uint160Set to query * @param timestamp The timestamp to check * @return array Array of active uint160s */ function getActive(Uint160Set storage self, uint48 timestamp) internal view returns (uint160[] memory array) { uint256 arrayLen = self.array.length; array = new uint160[](arrayLen); uint256 len; for (uint256 i; i < arrayLen; ++i) { if (self.array[i].status.wasActiveAt(timestamp)) { array[len++] = self.array[i].value; } } assembly { mstore(array, len) } return array; } /** * @notice Checks if a uint160 was active at a given timestamp * @param self The Uint160Set to query * @param timestamp The timestamp to check * @param value The uint160 to check * @return bool Whether the uint160 was active */ function wasActiveAt(Uint160Set storage self, uint48 timestamp, uint160 value) internal view returns (bool) { uint256 pos = self.positions[value]; return pos != 0 && self.array[pos - 1].status.wasActiveAt(timestamp); } /** * @notice Registers a new uint160 * @param self The Uint160Set to modify * @param timestamp The timestamp to set as enabled * @param value The uint160 to register */ function register(Uint160Set storage self, uint48 timestamp, uint160 value) internal { if (self.positions[value] != 0) revert AlreadyRegistered(); Inner160 storage element = self.array.push(); element.value = value; element.status.set(timestamp); self.positions[value] = self.array.length; } /** * @notice Pauses a uint160 * @param self The Uint160Set to modify * @param timestamp The timestamp to set as disabled * @param value The uint160 to pause */ function pause(Uint160Set storage self, uint48 timestamp, uint160 value) internal { if (self.positions[value] == 0) revert NotRegistered(); self.array[self.positions[value] - 1].status.disable(timestamp); } /** * @notice Unpauses a uint160 * @param self The Uint160Set to modify * @param timestamp The timestamp to set as enabled * @param immutablePeriod The required waiting period after disabling * @param value The uint160 to unpause */ function unpause(Uint160Set storage self, uint48 timestamp, uint48 immutablePeriod, uint160 value) internal { if (self.positions[value] == 0) revert NotRegistered(); self.array[self.positions[value] - 1].status.enable(timestamp, immutablePeriod); } /** * @notice Unregisters a uint160 * @param self The Uint160Set to modify * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling * @param value The uint160 to unregister */ function unregister(Uint160Set storage self, uint48 timestamp, uint48 immutablePeriod, uint160 value) internal { uint256 pos = self.positions[value]; if (pos == 0) revert NotRegistered(); pos--; self.array[pos].status.validateUnregister(timestamp, immutablePeriod); if (self.array.length <= pos + 1) { delete self.positions[value]; self.array.pop(); return; } self.array[pos] = self.array[self.array.length - 1]; self.array.pop(); delete self.positions[value]; self.positions[self.array[pos].value] = pos + 1; } /** * @notice Checks if a uint160 is registered * @param self The Uint160Set to query * @param value The uint160 to check * @return bool Whether the uint160 is registered */ function contains(Uint160Set storage self, uint160 value) internal view returns (bool) { return self.positions[value] != 0; } // Bytes32Set functions /** * @notice Gets the number of bytes32s in the set * @param self The Bytes32Set to query * @return uint256 The number of bytes32s */ function length( Bytes32Set storage self ) internal view returns (uint256) { return self.array.length; } /** * @notice Gets the bytes32 and status at a given position * @param self The Bytes32Set to query * @param pos The position to query * @return The bytes32, enabled timestamp, and disabled timestamp */ function at(Bytes32Set storage self, uint256 pos) internal view returns (bytes32, uint48, uint48) { return self.array[pos].get(); } /** * @notice Gets all active bytes32s at a given timestamp * @param self The Bytes32Set to query * @param timestamp The timestamp to check * @return array Array of active bytes32s */ function getActive(Bytes32Set storage self, uint48 timestamp) internal view returns (bytes32[] memory array) { uint256 arrayLen = self.array.length; array = new bytes32[](arrayLen); uint256 len; for (uint256 i; i < arrayLen; ++i) { if (self.array[i].status.wasActiveAt(timestamp)) { array[len++] = self.array[i].value; } } assembly { mstore(array, len) } return array; } /** * @notice Checks if a bytes32 was active at a given timestamp * @param self The Bytes32Set to query * @param timestamp The timestamp to check * @param value The bytes32 to check * @return bool Whether the bytes32 was active */ function wasActiveAt(Bytes32Set storage self, uint48 timestamp, bytes32 value) internal view returns (bool) { uint256 pos = self.positions[value]; return pos != 0 && self.array[pos - 1].status.wasActiveAt(timestamp); } /** * @notice Registers a new bytes32 * @param self The Bytes32Set to modify * @param timestamp The timestamp to set as enabled * @param value The bytes32 to register */ function register(Bytes32Set storage self, uint48 timestamp, bytes32 value) internal { if (self.positions[value] != 0) revert AlreadyRegistered(); uint256 pos = self.array.length; InnerBytes32 storage element = self.array.push(); element.value = value; element.status.set(timestamp); self.positions[value] = pos + 1; } /** * @notice Pauses a bytes32 * @param self The Bytes32Set to modify * @param timestamp The timestamp to set as disabled * @param value The bytes32 to pause */ function pause(Bytes32Set storage self, uint48 timestamp, bytes32 value) internal { if (self.positions[value] == 0) revert NotRegistered(); self.array[self.positions[value] - 1].status.disable(timestamp); } /** * @notice Unpauses a bytes32 * @param self The Bytes32Set to modify * @param timestamp The timestamp to set as enabled * @param immutablePeriod The required waiting period after disabling * @param value The bytes32 to unpause */ function unpause(Bytes32Set storage self, uint48 timestamp, uint48 immutablePeriod, bytes32 value) internal { if (self.positions[value] == 0) revert NotRegistered(); self.array[self.positions[value] - 1].status.enable(timestamp, immutablePeriod); } /** * @notice Checks if a bytes32 can be unregistered * @param self The Bytes32Set to query * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling * @param value The bytes32 to check * @return bool Whether the bytes32 can be unregistered */ function checkUnregister( Bytes32Set storage self, uint48 timestamp, uint48 immutablePeriod, bytes32 value ) internal view returns (bool) { uint256 pos = self.positions[value]; if (pos == 0) return false; return self.array[pos - 1].status.checkUnregister(timestamp, immutablePeriod); } /** * @notice Unregisters a bytes32 * @param self The Bytes32Set to modify * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling * @param value The bytes32 to unregister */ function unregister(Bytes32Set storage self, uint48 timestamp, uint48 immutablePeriod, bytes32 value) internal { uint256 pos = self.positions[value]; if (pos == 0) revert NotRegistered(); pos--; self.array[pos].status.validateUnregister(timestamp, immutablePeriod); if (self.array.length <= pos + 1) { delete self.positions[value]; self.array.pop(); return; } self.array[pos] = self.array[self.array.length - 1]; self.array.pop(); delete self.positions[value]; self.positions[self.array[pos].value] = pos + 1; } /** * @notice Checks if a bytes32 is registered * @param self The Bytes32Set to query * @param value The bytes32 to check * @return bool Whether the bytes32 is registered */ function contains(Bytes32Set storage self, bytes32 value) internal view returns (bool) { return self.positions[value] != 0; } // BytesSet functions /** * @notice Gets the number of bytes values in the set * @param self The BytesSet to query * @return uint256 The number of bytes values */ function length( BytesSet storage self ) internal view returns (uint256) { return self.array.length; } /** * @notice Gets the bytes value and status at a given position * @param self The BytesSet to query * @param pos The position to query * @return The bytes value, enabled timestamp, and disabled timestamp */ function at(BytesSet storage self, uint256 pos) internal view returns (bytes memory, uint48, uint48) { return self.array[pos].get(); } /** * @notice Gets all active bytes values at a given timestamp * @param self The BytesSet to query * @param timestamp The timestamp to check * @return array Array of active bytes values */ function getActive(BytesSet storage self, uint48 timestamp) internal view returns (bytes[] memory array) { uint256 arrayLen = self.array.length; array = new bytes[](arrayLen); uint256 len; for (uint256 i; i < arrayLen; ++i) { if (self.array[i].status.wasActiveAt(timestamp)) { array[len++] = self.array[i].value; } } assembly { mstore(array, len) } return array; } /** * @notice Checks if a bytes value was active at a given timestamp * @param self The BytesSet to query * @param timestamp The timestamp to check * @param value The bytes value to check * @return bool Whether the bytes value was active */ function wasActiveAt(BytesSet storage self, uint48 timestamp, bytes memory value) internal view returns (bool) { uint256 pos = self.positions[value]; return pos != 0 && self.array[pos - 1].status.wasActiveAt(timestamp); } /** * @notice Registers a new bytes value * @param self The BytesSet to modify * @param timestamp The timestamp to set as enabled * @param value The bytes value to register */ function register(BytesSet storage self, uint48 timestamp, bytes memory value) internal { if (self.positions[value] != 0) revert AlreadyRegistered(); uint256 pos = self.array.length; InnerBytes storage element = self.array.push(); element.value = value; element.status.set(timestamp); self.positions[value] = pos + 1; } /** * @notice Pauses a bytes value * @param self The BytesSet to modify * @param timestamp The timestamp to set as disabled * @param value The bytes value to pause */ function pause(BytesSet storage self, uint48 timestamp, bytes memory value) internal { if (self.positions[value] == 0) revert NotRegistered(); self.array[self.positions[value] - 1].status.disable(timestamp); } /** * @notice Unpauses a bytes value * @param self The BytesSet to modify * @param timestamp The timestamp to set as enabled * @param immutablePeriod The required waiting period after disabling * @param value The bytes value to unpause */ function unpause(BytesSet storage self, uint48 timestamp, uint48 immutablePeriod, bytes memory value) internal { if (self.positions[value] == 0) revert NotRegistered(); self.array[self.positions[value] - 1].status.enable(timestamp, immutablePeriod); } /** * @notice Checks if a bytes value can be unregistered * @param self The BytesSet to query * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling * @param value The bytes value to check * @return bool Whether the bytes value can be unregistered */ function checkUnregister( BytesSet storage self, uint48 timestamp, uint48 immutablePeriod, bytes memory value ) internal view returns (bool) { uint256 pos = self.positions[value]; if (pos == 0) return false; return self.array[pos - 1].status.checkUnregister(timestamp, immutablePeriod); } /** * @notice Unregisters a bytes value * @param self The BytesSet to modify * @param timestamp The current timestamp * @param immutablePeriod The required waiting period after disabling * @param value The bytes value to unregister */ function unregister(BytesSet storage self, uint48 timestamp, uint48 immutablePeriod, bytes memory value) internal { uint256 pos = self.positions[value]; if (pos == 0) revert NotRegistered(); pos--; self.array[pos].status.validateUnregister(timestamp, immutablePeriod); if (self.array.length <= pos + 1) { delete self.positions[value]; self.array.pop(); return; } self.array[pos] = self.array[self.array.length - 1]; self.array.pop(); delete self.positions[value]; self.positions[self.array[pos].value] = pos + 1; } /** * @notice Checks if a bytes value is registered * @param self The BytesSet to query * @param value The bytes value to check * @return bool Whether the bytes value is registered */ function contains(BytesSet storage self, bytes memory value) internal view returns (bool) { return self.positions[value] != 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @title CaptureTimestampManager * @notice Abstract contract for managing capture timestamps */ abstract contract CaptureTimestampManager is Initializable { /** * @notice Returns the current capture timestamp * @return timestamp The current capture timestamp */ function getCaptureTimestamp() public view virtual returns (uint48 timestamp); /** * @notice Returns the current timestamp * @return timestamp The current timestamp */ function _now() internal view returns (uint48) { return Time.timestamp(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @title StakePowerManager * @notice Abstract contract for managing stake power conversion */ abstract contract StakePowerManager is Initializable { /** * @notice Converts stake amount to voting power * @param vault The vault address * @param stake The stake amount * @return power The calculated voting power */ function stakeToPower(address vault, uint256 stake) public view virtual returns (uint256 power); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IBaseSlasher} from "./IBaseSlasher.sol"; interface IVetoSlasher is IBaseSlasher { error AlreadySet(); error InsufficientSlash(); error InvalidCaptureTimestamp(); error InvalidResolverSetEpochsDelay(); error InvalidVetoDuration(); error NoResolver(); error NotNetwork(); error NotResolver(); error SlashPeriodEnded(); error SlashRequestCompleted(); error SlashRequestNotExist(); error VetoPeriodEnded(); error VetoPeriodNotEnded(); /** * @notice Initial parameters needed for a slasher deployment. * @param baseParams base parameters for slashers' 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 { IBaseSlasher.BaseParams baseParams; 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 Extra data for the delegator. * @param slashableStake amount of the slashable stake before the slash (cache) * @param stakeAt amount of the stake at the capture time (cache) * @param slashIndex index of the slash request */ struct DelegatorData { uint256 slashableStake; uint256 stakeAt; uint256 slashIndex; } /** * @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 virtual 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 hint hint for the checkpoint index * @return address of the resolver */ function resolverAt(bytes32 subnetwork, uint48 timestamp, bytes memory hint) 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 virtual 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 {IBaseSlasher} from "./IBaseSlasher.sol"; interface ISlasher is IBaseSlasher { error InsufficientSlash(); error InvalidCaptureTimestamp(); /** * @notice Initial parameters needed for a slasher deployment. * @param baseParams base parameters for slashers' deployment */ struct InitParams { IBaseSlasher.BaseParams baseParams; } /** * @notice Hints for a slash. * @param slashableStakeHints hints for the slashable stake checkpoints */ struct SlashHints { bytes slashableStakeHints; } /** * @notice Extra data for the delegator. * @param slashableStake amount of the slashable stake before the slash (cache) * @param stakeAt amount of the stake at the capture time (cache) */ struct DelegatorData { uint256 slashableStake; uint256 stakeAt; } /** * @notice Emitted when a slash is performed. * @param subnetwork subnetwork that requested the slash * @param operator operator that is slashed * @param slashedAmount virtual 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 virtual 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; import {IBaseDelegator} from "./IBaseDelegator.sol"; interface IOperatorSpecificDelegator is IBaseDelegator { error DuplicateRoleHolder(); error ExceedsMaxNetworkLimit(); error MissingRoleHolders(); error NotOperator(); 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 */ struct StakeHints { bytes baseHints; bytes activeStakeHint; bytes networkLimitHint; } /** * @notice Initial parameters needed for an operator-specific delegator deployment. * @param baseParams base parameters for delegators' deployment * @param networkLimitSetRoleHolders array of addresses of the initial NETWORK_LIMIT_SET_ROLE holders * @param operator address of the single operator */ struct InitParams { IBaseDelegator.BaseParams baseParams; address[] networkLimitSetRoleHolders; address operator; } /** * @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 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 the operator registry's address. * @return address of the operator registry */ function OPERATOR_REGISTRY() external view returns (address); /** * @notice Get an operator managing the vault's funds. * @return address of the operator */ function operator() external view returns (address); /** * @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 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; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableMap.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. pragma solidity ^0.8.20; import {EnumerableSet} from "./EnumerableSet.sol"; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * The following map types are supported: * * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 * - `uint256 -> bytes32` (`UintToBytes32Map`) since v5.1.0 * - `address -> address` (`AddressToAddressMap`) since v5.1.0 * - `address -> bytes32` (`AddressToBytes32Map`) since v5.1.0 * - `bytes32 -> address` (`Bytes32ToAddressMap`) since v5.1.0 * * [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 EnumerableMap, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableMap. * ==== */ library EnumerableMap { using EnumerableSet for EnumerableSet.Bytes32Set; // To implement this library for multiple types with as little code repetition as possible, we write it in // terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions, // and user-facing implementations such as `UintToAddressMap` are just wrappers around the underlying Map. // This means that we can only create new EnumerableMaps for types that fit in bytes32. /** * @dev Query for a nonexistent map key. */ error EnumerableMapNonexistentKey(bytes32 key); struct Bytes32ToBytes32Map { // Storage of keys EnumerableSet.Bytes32Set _keys; mapping(bytes32 key => bytes32) _values; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) { map._values[key] = value; return map._keys.add(key); } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { delete map._values[key]; return map._keys.remove(key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { return map._keys.length(); } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32 key, bytes32 value) { bytes32 atKey = map._keys.at(index); return (atKey, map._values[atKey]); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool exists, bytes32 value) { bytes32 val = map._values[key]; if (val == bytes32(0)) { return (contains(map, key), bytes32(0)); } else { return (true, val); } } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { bytes32 value = map._values[key]; if (value == 0 && !contains(map, key)) { revert EnumerableMapNonexistentKey(key); } return value; } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) { return map._keys.values(); } // UintToUintMap struct UintToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. 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(UintToUintMap storage map, uint256 index) internal view returns (uint256 key, uint256 value) { (bytes32 atKey, bytes32 val) = at(map._inner, index); return (uint256(atKey), uint256(val)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool exists, uint256 value) { (bool success, bytes32 val) = tryGet(map._inner, bytes32(key)); return (success, uint256(val)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key))); } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToUintMap storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; assembly ("memory-safe") { result := store } return result; } // UintToAddressMap struct UintToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. 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(UintToAddressMap storage map, uint256 index) internal view returns (uint256 key, address value) { (bytes32 atKey, bytes32 val) = at(map._inner, index); return (uint256(atKey), address(uint160(uint256(val)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool exists, address value) { (bool success, bytes32 val) = tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(val)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key))))); } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; assembly ("memory-safe") { result := store } return result; } // UintToBytes32Map struct UintToBytes32Map { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToBytes32Map storage map, uint256 key, bytes32 value) internal returns (bool) { return set(map._inner, bytes32(key), value); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToBytes32Map storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToBytes32Map storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToBytes32Map storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. 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(UintToBytes32Map storage map, uint256 index) internal view returns (uint256 key, bytes32 value) { (bytes32 atKey, bytes32 val) = at(map._inner, index); return (uint256(atKey), val); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToBytes32Map storage map, uint256 key) internal view returns (bool exists, bytes32 value) { (bool success, bytes32 val) = tryGet(map._inner, bytes32(key)); return (success, val); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToBytes32Map storage map, uint256 key) internal view returns (bytes32) { return get(map._inner, bytes32(key)); } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToBytes32Map storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; assembly ("memory-safe") { result := store } return result; } // AddressToUintMap struct AddressToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToUintMap storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToUintMap storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. 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(AddressToUintMap storage map, uint256 index) internal view returns (address key, uint256 value) { (bytes32 atKey, bytes32 val) = at(map._inner, index); return (address(uint160(uint256(atKey))), uint256(val)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToUintMap storage map, address key) internal view returns (bool exists, uint256 value) { (bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, uint256(val)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToUintMap storage map, address key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))))); } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(AddressToUintMap storage map) internal view returns (address[] memory) { bytes32[] memory store = keys(map._inner); address[] memory result; assembly ("memory-safe") { result := store } return result; } // AddressToAddressMap struct AddressToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToAddressMap storage map, address key, address value) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToAddressMap storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToAddressMap storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. 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(AddressToAddressMap storage map, uint256 index) internal view returns (address key, address value) { (bytes32 atKey, bytes32 val) = at(map._inner, index); return (address(uint160(uint256(atKey))), address(uint160(uint256(val)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool exists, address value) { (bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, address(uint160(uint256(val)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToAddressMap storage map, address key) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(uint256(uint160(key))))))); } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(AddressToAddressMap storage map) internal view returns (address[] memory) { bytes32[] memory store = keys(map._inner); address[] memory result; assembly ("memory-safe") { result := store } return result; } // AddressToBytes32Map struct AddressToBytes32Map { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToBytes32Map storage map, address key, bytes32 value) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), value); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToBytes32Map storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToBytes32Map storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. 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(AddressToBytes32Map storage map, uint256 index) internal view returns (address key, bytes32 value) { (bytes32 atKey, bytes32 val) = at(map._inner, index); return (address(uint160(uint256(atKey))), val); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToBytes32Map storage map, address key) internal view returns (bool exists, bytes32 value) { (bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, val); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToBytes32Map storage map, address key) internal view returns (bytes32) { return get(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(AddressToBytes32Map storage map) internal view returns (address[] memory) { bytes32[] memory store = keys(map._inner); address[] memory result; assembly ("memory-safe") { result := store } return result; } // Bytes32ToUintMap struct Bytes32ToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) { return set(map._inner, key, bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { return remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { return contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. 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(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32 key, uint256 value) { (bytes32 atKey, bytes32 val) = at(map._inner, index); return (atKey, uint256(val)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool exists, uint256 value) { (bool success, bytes32 val) = tryGet(map._inner, key); return (success, uint256(val)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { return uint256(get(map._inner, key)); } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) { bytes32[] memory store = keys(map._inner); bytes32[] memory result; assembly ("memory-safe") { result := store } return result; } // Bytes32ToAddressMap struct Bytes32ToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToAddressMap storage map, bytes32 key, address value) internal returns (bool) { return set(map._inner, key, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToAddressMap storage map, bytes32 key) internal returns (bool) { return remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool) { return contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. 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(Bytes32ToAddressMap storage map, uint256 index) internal view returns (bytes32 key, address value) { (bytes32 atKey, bytes32 val) = at(map._inner, index); return (atKey, address(uint160(uint256(val)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool exists, address value) { (bool success, bytes32 val) = tryGet(map._inner, key); return (success, address(uint160(uint256(val)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (address) { return address(uint160(uint256(get(map._inner, key)))); } /** * @dev Return the an array containing all the keys * * 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 map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToAddressMap storage map) internal view returns (bytes32[] memory) { bytes32[] memory store = keys(map._inner); bytes32[] memory result; assembly ("memory-safe") { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @title NetworkStorage * @notice Storage contract for managing the network address * @dev Uses a single storage slot to store the network address value */ abstract contract NetworkStorage is Initializable { // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.NetworkStorage")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant NetworkStorageLocation = 0x779150488f5e984d1f840ba606e388ada6c73b44f261274c3595c61a30023e00; /** * @notice Initializes the NetworkManager contract * @param network The address of the network */ function __NetworkStorage_init_private( address network ) internal onlyInitializing { assembly { sstore(NetworkStorageLocation, network) } } /** * @notice Returns the address of the network * @return network The address of the network */ function _NETWORK() internal view returns (address) { address network; assembly { network := sload(NetworkStorageLocation) } return network; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.25; import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @title SlashingWindowStorage * @notice Storage contract for managing the slashing window duration * @dev Uses a single storage slot to store the slashing window duration value */ abstract contract SlashingWindowStorage is Initializable { // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.SlashingWindowStorage")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant SlashingWindowStorageLocation = 0x52becd5b30d67421b1f63b9d90d513daf82b3973912d3edfdac9468c1743c000; /** * @notice Initializes the SlashingWindowStorage contract * @param _slashingWindow The duration of the slashing window in seconds */ function __SlashingWindowStorage_init_private( uint48 _slashingWindow ) internal onlyInitializing { assembly { sstore(SlashingWindowStorageLocation, _slashingWindow) } } /** * @notice Returns the slashing window duration * @return slashingWindow The duration of the slashing window in seconds */ function _SLASHING_WINDOW() internal view returns (uint48) { uint48 slashingWindow; assembly { slashingWindow := sload(SlashingWindowStorageLocation) } return slashingWindow; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IOptInService { error AlreadyOptedIn(); error ExpiredSignature(); error InvalidSignature(); 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 Emitted when the nonce of a "who" to a "where" entity is increased. * @param who address of the "who" * @param where address of the "where" entity */ event IncreaseNonce(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" entity * @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" entity * @return if the "who" is opted-in */ function isOptedIn(address who, address where) external view returns (bool); /** * @notice Get the nonce of a given "who" to a particular "where" entity. * @param who address of the "who" * @param where address of the "where" entity * @return nonce */ function nonces(address who, address where) external view returns (uint256); /** * @notice Opt-in a calling "who" to a particular "where" entity. * @param where address of the "where" entity */ function optIn( address where ) external; /** * @notice Opt-in a "who" to a particular "where" entity with a signature. * @param who address of the "who" * @param where address of the "where" entity * @param deadline time point until the signature is valid (inclusively) * @param signature signature of the "who" */ function optIn(address who, address where, uint48 deadline, bytes calldata signature) external; /** * @notice Opt-out a calling "who" from a particular "where" entity. * @param where address of the "where" entity */ function optOut( address where ) external; /** * @notice Opt-out a "who" from a particular "where" entity with a signature. * @param who address of the "who" * @param where address of the "where" entity * @param deadline time point until the signature is valid (inclusively) * @param signature signature of the "who" */ function optOut(address who, address where, uint48 deadline, bytes calldata signature) external; /** * @notice Increase the nonce of a given "who" to a particular "where" entity. * @param where address of the "where" entity * @dev It can be used to invalidate a given signature. */ function increaseNonce( address where ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.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[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an ERC-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) { assembly ("memory-safe") { 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 ERC-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 ERC-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 (ERC-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) { assembly ("memory-safe") { 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) (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.1.0) (utils/types/Time.sol) pragma solidity ^0.8.20; import {Math} from "../math/Math.sol"; import {SafeCast} from "../math/SafeCast.sol"; /** * @dev This library provides helpers for manipulating time-related objects. * * It uses the following types: * - `uint48` for timepoints * - `uint32` for durations * * While the library doesn't provide specific types for timepoints and duration, it does provide: * - a `Delay` type to represent duration that can be programmed to change value automatically at a given point * - additional helper functions */ library Time { using Time for *; /** * @dev Get the block timestamp as a Timepoint. */ function timestamp() internal view returns (uint48) { return SafeCast.toUint48(block.timestamp); } /** * @dev Get the block number as a Timepoint. */ function blockNumber() internal view returns (uint48) { return SafeCast.toUint48(block.number); } // ==================================================== Delay ===================================================== /** * @dev A `Delay` is a uint32 duration that can be programmed to change value automatically at a given point in the * future. The "effect" timepoint describes when the transitions happens from the "old" value to the "new" value. * This allows updating the delay applied to some operation while keeping some guarantees. * * In particular, the {update} function guarantees that if the delay is reduced, the old delay still applies for * some time. For example if the delay is currently 7 days to do an upgrade, the admin should not be able to set * the delay to 0 and upgrade immediately. If the admin wants to reduce the delay, the old delay (7 days) should * still apply for some time. * * * The `Delay` type is 112 bits long, and packs the following: * * ``` * | [uint48]: effect date (timepoint) * | | [uint32]: value before (duration) * ↓ ↓ ↓ [uint32]: value after (duration) * 0xAAAAAAAAAAAABBBBBBBBCCCCCCCC * ``` * * NOTE: The {get} and {withUpdate} functions operate using timestamps. Block number based delays are not currently * supported. */ type Delay is uint112; /** * @dev Wrap a duration into a Delay to add the one-step "update in the future" feature */ function toDelay(uint32 duration) internal pure returns (Delay) { return Delay.wrap(duration); } /** * @dev Get the value at a given timepoint plus the pending value and effect timepoint if there is a scheduled * change after this timepoint. If the effect timepoint is 0, then the pending value should not be considered. */ function _getFullAt( Delay self, uint48 timepoint ) private pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) { (valueBefore, valueAfter, effect) = self.unpack(); return effect <= timepoint ? (valueAfter, 0, 0) : (valueBefore, valueAfter, effect); } /** * @dev Get the current value plus the pending value and effect timepoint if there is a scheduled change. If the * effect timepoint is 0, then the pending value should not be considered. */ function getFull(Delay self) internal view returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) { return _getFullAt(self, timestamp()); } /** * @dev Get the current value. */ function get(Delay self) internal view returns (uint32) { (uint32 delay, , ) = self.getFull(); return delay; } /** * @dev Update a Delay object so that it takes a new duration after a timepoint that is automatically computed to * enforce the old delay at the moment of the update. Returns the updated Delay object and the timestamp when the * new delay becomes effective. */ function withUpdate( Delay self, uint32 newValue, uint32 minSetback ) internal view returns (Delay updatedDelay, uint48 effect) { uint32 value = self.get(); uint32 setback = uint32(Math.max(minSetback, value > newValue ? value - newValue : 0)); effect = timestamp() + setback; return (pack(value, newValue, effect), effect); } /** * @dev Split a delay into its components: valueBefore, valueAfter and effect (transition timepoint). */ function unpack(Delay self) internal pure returns (uint32 valueBefore, uint32 valueAfter, uint48 effect) { uint112 raw = Delay.unwrap(self); valueAfter = uint32(raw); valueBefore = uint32(raw >> 32); effect = uint48(raw >> 64); return (valueBefore, valueAfter, effect); } /** * @dev pack the components into a Delay object. */ function pack(uint32 valueBefore, uint32 valueAfter, uint48 effect) internal pure returns (Delay) { return Delay.wrap((uint112(effect) << 64) | (uint112(valueBefore) << 32) | uint112(valueAfter)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IEntity} from "../common/IEntity.sol"; interface IBaseSlasher is IEntity { error NoBurner(); error InsufficientBurnerGas(); error NotNetworkMiddleware(); error NotVault(); /** * @notice Base parameters needed for slashers' deployment. * @param isBurnerHook if the burner is needed to be called on a slashing */ struct BaseParams { bool isBurnerHook; } /** * @notice Hints for a slashable stake. * @param stakeHints hints for the stake checkpoints * @param cumulativeSlashFromHint hint for the cumulative slash amount at a capture timestamp */ struct SlashableStakeHints { bytes stakeHints; bytes cumulativeSlashFromHint; } /** * @notice General data for the delegator. * @param slasherType type of the slasher * @param data slasher-dependent data for the delegator */ struct GeneralDelegatorData { uint64 slasherType; bytes data; } /** * @notice Get a gas limit for the burner. * @return value of the burner gas limit */ function BURNER_GAS_LIMIT() external view returns (uint256); /** * @notice Get a reserve gas between the gas limit check and the burner's execution. * @return value of the reserve gas */ function BURNER_RESERVE() external view returns (uint256); /** * @notice Get the vault factory's address. * @return address of the vault factory */ function VAULT_FACTORY() external view returns (address); /** * @notice Get the network middleware service's address. * @return address of the network middleware service */ function NETWORK_MIDDLEWARE_SERVICE() external view returns (address); /** * @notice Get the vault's address. * @return address of the vault to perform slashings on */ function vault() external view returns (address); /** * @notice Get if the burner is needed to be called on a slashing. * @return if the burner is a hook */ function isBurnerHook() external view returns (bool); /** * @notice Get the latest capture timestamp that was slashed on a subnetwork. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @return latest capture timestamp that was slashed */ function latestSlashedCaptureTimestamp(bytes32 subnetwork, address operator) external view returns (uint48); /** * @notice Get a cumulative slash amount for an operator on a subnetwork until a given timestamp (inclusively) using a hint. * @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 cumulative slash amount until (inclusively) * @param hint hint for the checkpoint index * @return cumulative slash amount until the given timestamp (inclusively) */ function cumulativeSlashAt( bytes32 subnetwork, address operator, uint48 timestamp, bytes memory hint ) external view returns (uint256); /** * @notice Get a cumulative slash amount for an operator on a subnetwork. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @return cumulative slash amount */ function cumulativeSlash(bytes32 subnetwork, address operator) external view returns (uint256); /** * @notice Get a slashable amount of a stake got at a given capture timestamp 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 captureTimestamp time point to get the stake amount at * @param hints hints for the checkpoints' indexes * @return slashable amount of the stake */ function slashableStake( bytes32 subnetwork, address operator, uint48 captureTimestamp, bytes memory hints ) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.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; assembly ("memory-safe") { 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; assembly ("memory-safe") { 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; assembly ("memory-safe") { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SafeCast} from "./math/SafeCast.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { using SafeCast for *; 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 The string being parsed contains characters that are not in scope of the given base. */ error StringsInvalidChar(); /** * @dev The string being parsed is not a properly formatted address. */ error StringsInvalidAddressFormat(); /** * @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; assembly ("memory-safe") { ptr := add(buffer, add(32, length)) } while (true) { ptr--; assembly ("memory-safe") { 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 Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal * representation, according to EIP-55. */ function toChecksumHexString(address addr) internal pure returns (string memory) { bytes memory buffer = bytes(toHexString(addr)); // hash the hex part of buffer (skip length + 2 bytes, length 40) uint256 hashValue; assembly ("memory-safe") { hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) } for (uint256 i = 41; i > 1; --i) { // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { // case shift by xoring with 0x20 buffer[i] ^= 0x20; } hashValue >>= 4; } return string(buffer); } /** * @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)); } /** * @dev Parse a decimal string and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input) internal pure returns (uint256) { return parseUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) { return tryParseUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); uint256 result = 0; for (uint256 i = begin; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 9) return (false, 0); result *= 10; result += chr; } return (true, result); } /** * @dev Parse a decimal string and returns the value as a `int256`. * * Requirements: * - The string must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input) internal pure returns (int256) { return parseInt(input, 0, bytes(input).length); } /** * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) { (bool success, int256 value) = tryParseInt(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if * the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt(string memory input) internal pure returns (bool success, int256 value) { return tryParseInt(input, 0, bytes(input).length); } uint256 private constant ABS_MIN_INT256 = 2 ** 255; /** * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character or if the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, int256 value) { bytes memory buffer = bytes(input); // Check presence of a negative sign. bytes1 sign = bytes1(_unsafeReadBytesOffset(buffer, begin)); bool positiveSign = sign == bytes1("+"); bool negativeSign = sign == bytes1("-"); uint256 offset = (positiveSign || negativeSign).toUint(); (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end); if (absSuccess && absValue < ABS_MIN_INT256) { return (true, negativeSign ? -int256(absValue) : int256(absValue)); } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) { return (true, type(int256).min); } else return (false, 0); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input) internal pure returns (uint256) { return parseHexUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseHexUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) { return tryParseHexUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an * invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); // skip 0x prefix if present bool hasPrefix = bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); uint256 offset = hasPrefix.toUint() * 2; uint256 result = 0; for (uint256 i = begin + offset; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 15) return (false, 0); result *= 16; unchecked { // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check). // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked. result += chr; } } return (true, result); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input) internal pure returns (address) { return parseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) { (bool success, address value) = tryParseAddress(input, begin, end); if (!success) revert StringsInvalidAddressFormat(); return value; } /** * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress(string memory input) internal pure returns (bool success, address value) { return tryParseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, address value) { // check that input is the correct length bool hasPrefix = bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); uint256 expectedLength = 40 + hasPrefix.toUint() * 2; if (end - begin == expectedLength) { // length guarantees that this does not overflow, and value is at most type(uint160).max (bool s, uint256 v) = tryParseHexUint(input, begin, end); return (s, address(uint160(v))); } else { return (false, address(0)); } } function _tryParseChr(bytes1 chr) private pure returns (uint8) { uint8 value = uint8(chr); // Try to parse `chr`: // - Case 1: [0-9] // - Case 2: [a-f] // - Case 3: [A-F] // - otherwise not supported unchecked { if (value > 47 && value < 58) value -= 48; else if (value > 96 && value < 103) value -= 87; else if (value > 64 && value < 71) value -= 55; else return type(uint8).max; } return value; } /** * @dev Reads a bytes32 from a bytes array without bounds checking. * * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the * assembly block as such would prevent some optimizations. */ function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { // This is not memory safe in the general case, but all calls to this private function are within bounds. assembly ("memory-safe") { value := mload(add(buffer, add(0x20, offset))) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); } } /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return ternary(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 { // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, // taking advantage of the most significant (or "sign" bit) in two's complement representation. // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative). int256 mask = n >> 255; // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. return uint256((n + mask) ^ mask); } } }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@symbiotic/=lib/core/src/", "@symbiotic-test/=lib/core/test/", "@crypto-lib/=lib/crypto-lib/src/", "@solidity/=lib/crypto-lib/src/", "core/=lib/core/", "crypto-lib/=lib/crypto-lib/", "ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"networkRegistry","type":"address"},{"internalType":"uint48","name":"slashingWindow","type":"uint48"},{"internalType":"address","name":"operatorRegistry","type":"address"},{"internalType":"address","name":"vaultRegistry","type":"address"},{"internalType":"address","name":"operatorNetOptin","type":"address"},{"internalType":"address","name":"reader","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyEnabled","type":"error"},{"inputs":[],"name":"AlreadyRegistered","type":"error"},{"inputs":[],"name":"DuplicateKey","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":"Enabled","type":"error"},{"inputs":[],"name":"ImmutablePeriodNotPassed","type":"error"},{"inputs":[],"name":"InactiveValidator","type":"error"},{"inputs":[],"name":"InactiveVaultSlash","type":"error"},{"inputs":[],"name":"InvalidHints","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"InvalidOwner","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"MaxDisabledKeysReached","type":"error"},{"inputs":[],"name":"NoSlasher","type":"error"},{"inputs":[],"name":"NonVetoSlasher","type":"error"},{"inputs":[],"name":"NotEnabled","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NotOperator","type":"error"},{"inputs":[],"name":"NotOperatorSpecificVault","type":"error"},{"inputs":[],"name":"NotOperatorVault","type":"error"},{"inputs":[],"name":"NotRegistered","type":"error"},{"inputs":[],"name":"NotVault","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"OnlyOwnerCanCall","type":"error"},{"inputs":[],"name":"OperatorNotOptedIn","type":"error"},{"inputs":[],"name":"OperatorNotRegistered","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[],"name":"TaskCompleted","type":"error"},{"inputs":[],"name":"TooManyOperatorVaults","type":"error"},{"inputs":[],"name":"TooOldTimestampSlash","type":"error"},{"inputs":[],"name":"UnknownSlasherType","type":"error"},{"inputs":[],"name":"VaultAlreadyRegistered","type":"error"},{"inputs":[],"name":"VaultEpochTooShort","type":"error"},{"inputs":[],"name":"VaultNotInitialized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"taskIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isValidAnswer","type":"bool"}],"name":"CompleteTask","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"taskIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"validator","type":"address"}],"name":"CreateTask","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"bytes32","name":"subnetwork","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InstantSlash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"bytes32","name":"subnetwork","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"VetoSlash","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"BaseMiddleware_VERSION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ECDSASig_VERSION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KeyManagerAddress_VERSION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_OPERATOR_VAULTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OwnableAccessManager_VERSION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SelfRegisterOperators_VERSION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SharedVaults_VERSION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TimestampCapture_VERSION","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"taskIndex","type":"uint256"},{"internalType":"uint256","name":"answer","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes[]","name":"stakeHints","type":"bytes[]"},{"internalType":"bytes[]","name":"slashHints","type":"bytes[]"}],"name":"completeTask","outputs":[{"internalType":"bool","name":"isValidAnswer","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"validator","type":"address"}],"name":"createTask","outputs":[{"internalType":"uint256","name":"taskIndex","type":"uint256"}],"stateMutability":"nonpayable","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":"uint48","name":"epochStart","type":"uint48"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes32","name":"subnetwork","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"hints","type":"bytes"}],"name":"executeSlash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCaptureTimestamp","outputs":[{"internalType":"uint48","name":"timestamp","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint48","name":"timestamp","type":"uint48"},{"internalType":"bytes","name":"key_","type":"bytes"}],"name":"keyWasActiveAt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"key","type":"bytes"}],"name":"operatorByKey","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"operatorKey","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"pauseOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"pauseOperatorVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"pauseOperatorVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sharedVault","type":"address"}],"name":"pauseSharedVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"recover","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"key","type":"bytes"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"keySignature","type":"bytes"}],"name":"registerOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"key","type":"bytes"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"registerOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"registerOperatorVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"registerOperatorVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sharedVault","type":"address"}],"name":"registerSharedVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"stake","type":"uint256"}],"name":"stakeToPower","outputs":[{"internalType":"uint256","name":"power","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tasks","outputs":[{"internalType":"uint48","name":"captureTimestamp","type":"uint48"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address","name":"validator","type":"address"},{"internalType":"bool","name":"completed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"unpauseOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"unpauseOperatorVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"unpauseOperatorVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sharedVault","type":"address"}],"name":"unpauseSharedVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unregisterOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"unregisterOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"unregisterOperatorVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"unregisterOperatorVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sharedVault","type":"address"}],"name":"unregisterSharedVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"key","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"keySignature","type":"bytes"}],"name":"updateOperatorKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"key","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateOperatorKey","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561000f575f80fd5b50604051614fc8380380614fc883398101604081905261002e91610636565b61003d87878688878787610049565b50505050505050610815565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff1615906001600160401b03165f811580156100925750825b90505f826001600160401b031660011480156100ad5750303b155b9050811580156100bb575080155b156100d95760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b0319166001178555831561010757845460ff60401b1916680100000000000000001785555b8b6001600160a01b03166387140b5b6040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561013f575f80fd5b505af1158015610151573d5f803e3d5ffd5b50505050610169308c8c8c8c8c61020360201b60201c565b61017286610259565b60408051808201909152601e81527f53656c665265676973746572537172745461736b4d6964646c6577617265000060208201526101af9061026d565b83156101f557845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050505050565b61020b61029e565b610214866102ee565b61021d8561031a565b61022684610346565b6102308383610395565b7ffd87879bc98f37af7578af722aecfbe5843e5ad354da2d1e70cb5157c4ec8800555050505050565b61026161029e565b61026a81610409565b50565b61027561029e565b61026a81604051806040016040528060018152602001603160f81b81525061045b60201b60201c565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166102ec57604051631afcd79f60e31b815260040160405180910390fd5b565b6102f661029e565b7f779150488f5e984d1f840ba606e388ada6c73b44f261274c3595c61a30023e0055565b61032261029e565b7f52becd5b30d67421b1f63b9d90d513daf82b3973912d3edfdac9468c1743c00055565b61034e61029e565b7f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db0080546001600160a01b0319166001600160a01b0383161781556103915f61046d565b5050565b61039d61029e565b7f3b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e0080546001600160a01b039384166001600160a01b0319918216179091557f3b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e018054929093169116179055565b6001600160a01b0381166104375760405163b20f76e360e01b81525f60048201526024015b60405180910390fd5b7fcee92923a0c63eca6fc0402d78c9efde9f9f3dc73e6f9e14501bf734ed77f10055565b61046361029e565b61039182826104ad565b7f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db0061039161049961051f565b60018301906001600160601b03851661052d565b6104b561029e565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1007fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102610501848261075b565b5060038101610510838261075b565b505f8082556001909101555050565b5f6105286105e0565b905090565b6001600160a01b0381165f9081526001840160205260409020541561056557604051630ea075bf60e21b815260040160405180910390fd5b8254600180820185555f85815260209020600290920290910180546001600160a01b0319166001600160a01b038416178155906105ba9082018481546001600160601b03191665ffffffffffff909116179055565b5082546001600160a01b039091165f908152600190930160205260409092209190915550565b5f610528425f65ffffffffffff821115610617576040516306dfcc6560e41b8152603060048201526024810183905260440161042e565b5090565b80516001600160a01b0381168114610631575f80fd5b919050565b5f805f805f805f60e0888a03121561064c575f80fd5b6106558861061b565b9650602088015165ffffffffffff8116811461066f575f80fd5b955061067d6040890161061b565b945061068b6060890161061b565b93506106996080890161061b565b92506106a760a0890161061b565b91506106b560c0890161061b565b905092959891949750929550565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806106eb57607f821691505b60208210810361070957634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561075657805f5260205f20601f840160051c810160208510156107345750805b601f840160051c820191505b81811015610753575f8155600101610740565b50505b505050565b81516001600160401b03811115610774576107746106c3565b6107888161078284546106d7565b8461070f565b6020601f8211600181146107ba575f83156107a35750848201515b5f19600385901b1c1916600184901b178455610753565b5f84815260208120601f198516915b828110156107e957878501518255602094850194600190920191016107c9565b508482101561080657868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b6147a6806108225f395ff3fe608060405234801561000f575f80fd5b506004361061027d575f3560e01c806369f83e4b1161015a5780639c99bd75116100cc578063c84cde4411610085578063c84cde441461061e578063c9584f6214610631578063ca2d2a1814610644578063ce8c187014610657578063db3adf121461066a578063f81d58ff146106895761027d565b80639c99bd751461035c578063a876b89a146105d0578063b1630faa146105d8578063b18125be146105eb578063b38de8b41461060b578063c3778f161461035c5761027d565b80637ecebe001161011e5780637ecebe001461051a57806384af63241461054e57806384b0196e146105615780638bd872ab1461035c5780638d9776721461057c5780638da5cb5b146105c85761027d565b806369f83e4b146104c65780636d408712146104d9578063715018a6146104ec5780637664c514146104f457806377451229146105075761027d565b8063348d6335116101f357806347bab83d116101b757806347bab83d146104855780634afdcbde146104985780635210ca021461035c57806354b0116b146104a05780635b2191fa146104b35780635d991c961461035c5761027d565b8063348d6335146104265780633e030fab146104395780633e1ad83f1461044c578063458cc5421461045f57806347449640146104725761027d565b806319045a251161024557806319045a25146103aa5780631e0f2e1f146103d5578063292a8a9b146103f85780633280779e1461040b578063329685571461035c57806332e9181e1461041e5761027d565b806303426e7a1461033457806308e809f0146103495780630a0530ea1461035c57806313af4035146103815780631451178814610394575b5f7ffd87879bc98f37af7578af722aecfbe5843e5ad354da2d1e70cb5157c4ec88005490505f80826001600160a01b03165f36306040516020016102c393929190613c2c565b60408051601f19818403018152908290526102dd91613c4d565b5f60405180830381855af49150503d805f8114610315576040519150601f19603f3d011682016040523d82523d5f602084013e61031a565b606091505b50915091508161032c57805160208201fd5b805160208201f35b610347610342366004613c77565b61069c565b005b610347610357366004613c77565b6106a9565b610364600181565b6040516001600160401b0390911681526020015b60405180910390f35b61034761038f366004613c77565b6106ba565b61039c601481565b604051908152602001610378565b6103bd6103b8366004613d2f565b6106cb565b6040516001600160a01b039091168152602001610378565b6103e86103e3366004613d85565b6106df565b6040519015158152602001610378565b610347610406366004613c77565b610744565b610347610419366004613dbb565b61074e565b610347610809565b610347610434366004613e18565b610814565b610347610447366004613dbb565b6108e1565b6103bd61045a366004613eb6565b610971565b61034761046d366004613ee7565b6109bf565b610347610480366004613c77565b610a82565b610347610493366004613c77565b610a93565b610347610a9d565b6103476104ae366004613f97565b610aa6565b6103476104c1366004613fdb565b610ac1565b6103476104d4366004613dbb565b610b58565b6103476104e7366004613ff7565b610bc2565b610347610be1565b610347610502366004613c77565b610bf2565b61039c610515366004614078565b610bfc565b61039c610528366004613c77565b6001600160a01b03165f9081525f805160206146d1833981519152602052604090205490565b61039c61055c3660046140a6565b919050565b610569610d68565b60405161037897969594939291906140fe565b61058f61058a366004614194565b610e16565b6040805165ffffffffffff909516855260208501939093526001600160a01b039091169183019190915215156060820152608001610378565b6103bd610e64565b610347610e92565b6103476105e6366004613c77565b610e9b565b6105fe6105f9366004613c77565b610eac565b60405161037891906141ab565b610347610619366004613dbb565b610f4c565b61034761062c366004613fdb565b610fb6565b61034761063f3660046141bd565b61101d565b610347610652366004613c77565b611036565b610347610665366004613fdb565b611047565b6106726110ae565b60405165ffffffffffff9091168152602001610378565b6103e8610697366004614251565b6110c3565b6106a63382611166565b50565b6106b16111a0565b6106a6816111f5565b6106c26111a0565b6106a681611229565b5f6106d68383611276565b90505b92915050565b5f805f8051602061475183398151915290505f83806020019051810190610706919061432d565b6001600160a01b038082165f90815260018501602090815260408083205490931682528590522090915061073b90868361129e565b95945050505050565b6106a633826112b4565b6001600160a01b0383165f9081525f805160206146d1833981519152602081905260408220805491926107f99287927f3f13cbea81d7441d3504384770639bed665f2fdd45100939f9d93abca2708a02928492899290916107ae8361435c565b909155506040805160208101959095526001600160a01b039384169085015291166060830152608082015260a0015b60405160208183030381529060405280519060200120846112be565b61080384846112ee565b50505050565b610812336112f8565b565b61081f848483611301565b82516020808501919091206001600160a01b0386165f9081525f805160206146d1833981519152928390526040812080546108d09389937f1a8c1411ba00c3d249f48c949873f9596d266a13be61f3bc73c9e40f8bf470ba938593916108848361435c565b909155506040805160208101959095526001600160a01b03909316928401929092526060830152608082015260a0015b60405160208183030381529060405280519060200120856112be565b6108da8585611337565b5050505050565b6108ea83611341565b610907576040516325ec6c1f60e01b815260040160405180910390fd5b6001600160a01b0383165f9081525f805160206146d1833981519152602081905260408220805491926109679287927f616558fa4c156951628ff577e43a2ffbe2624ffe99f75a9f57c50a310530064d928492899290916107ae8361435c565b6108038484611166565b5f805f805160206147518339815191529050806001015f8480602001905181019061099c919061432d565b6001600160a01b03908116825260208201929092526040015f2054169392505050565b6109ca858583611301565b83516020808601919091206001600160a01b0387165f9081525f805160206146d183398151915292839052604081208054610a6f938a937f28e2348304d9c105deffd086bc056c631de89c293d37fe5623eae873d82969cc9385938b92909190610a338361435c565b909155506040805160208101969096526001600160a01b03948516908601526060850192909252909116608083015260a082015260c0016108b4565b610a7a86868661137a565b505050505050565b610a8a6111a0565b6106a6816113b0565b6106a633826113e4565b610812336113ee565b610ab1338483611301565b610abc33848461137a565b505050565b6001600160a01b0382165f9081525f805160206146d183398151915260208190526040822080549192610b4f9286927ff4b5ceebc7b665a989c88fb1987d90ecaa1646a6f4a3d02f7c33434f68567a029284929190610b1f8361435c565b919050556040516020016107dd939291909283526001600160a01b03919091166020830152604082015260600190565b610abc836113ee565b6001600160a01b0383165f9081525f805160206146d183398151915260208190526040822080549192610bb89287927f40ca710eba568c6bc31e352337f7e0f89b32dce800b1156ccb725edf2d15adc6928492899290916107ae8361435c565b61080384846113e4565b610bca6111a0565b610bd88686868686866113f7565b50505050505050565b610be96111a0565b6108125f611229565b6106a633826112ee565b604080516001600160a01b03831660208201525f9182910160405160208183030381529060405290505f610c2f82610971565b9050610c42610c3c6110ae565b836106df565b610c5f5760405163754e047b60e11b815260040160405180910390fd5b610c6881611341565b610c85576040516325ec6c1f60e01b815260040160405180910390fd5b5f8054905092505f6040518060800160405280610ca06110ae565b65ffffffffffff908116825260208083018a90526001600160a01b03808a1660408086018290525f6060968701819052885460018181018b55998252858220895160039092020180549190971665ffffffffffff199091161786559387015197850197909755858701516002909401805496909501511515600160a01b026001600160a81b0319909616939091169290921793909317909155915185917fb250fc64dc0fe8dc601cf62d8a1e52cd0827cbf95d4585c8117c95567740d12891a3505092915050565b5f60608082808083815f805160206147318339815191528054909150158015610d9357506001810154155b610ddc5760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b60448201526064015b60405180910390fd5b610de46117ab565b610dec61186b565b604080515f80825260208201909252600f60f81b9c939b5091995046985030975095509350915050565b5f8181548110610e24575f80fd5b5f91825260209091206003909102018054600182015460029092015465ffffffffffff90911692506001600160a01b03811690600160a01b900460ff1684565b5f610e8d7fcee92923a0c63eca6fc0402d78c9efde9f9f3dc73e6f9e14501bf734ed77f1005490565b905090565b610812336118a9565b610ea36111a0565b6106a6816118b2565b60605f805160206147518339815191525f610ee5610ec86110ae565b6001600160a01b0386165f908152602085905260409020906118d6565b905080515f03610f1357604080515f6020820152015b60405160208183030381529060405292505050919050565b805f81518110610f2557610f25614374565b6020026020010151604051602001610efb91906001600160a01b0391909116815260200190565b6001600160a01b0383165f9081525f805160206146d183398151915260208190526040822080549192610fac9287927ff8c72a3aa921e817ca53424f4d187362d26d249fdcee703fee36ad92b9142771928492899290916107ae8361435c565b61080384846112b4565b6001600160a01b0382165f9081525f805160206146d1833981519152602081905260408220805491926110149286927f49584bafbd77382376a35a9d49efaacece2be43b76c8e96aff93c9b6742410719284929190610b1f8361435c565b610abc836112f8565b611028338383611301565b6110323383611337565b5050565b61103e6111a0565b6106a6816118eb565b6001600160a01b0382165f9081525f805160206146d1833981519152602081905260408220805491926110a59286927ffebeac2fb9f2c5f3e90991eb339385576ae705aa0dd905a9f965f8b76ba598409284929190610b1f8361435c565b610abc836118a9565b5f60016110b9611918565b610e8d9190614388565b5f6110d089898989611921565b905060015f8a815481106110e6576110e6614374565b905f5260205f20906003020160020160146101000a81548160ff0219169083151502179055508061111e5761111e8986868686611985565b887fa4a1d94d1676fe30c56127e96641c5e95021748f1e6b8271009dde8177cc2ab482604051611152911515815260200190565b60405180910390a298975050505050505050565b61116f82611341565b61118c576040516325ec6c1f60e01b815260040160405180910390fd5b61119682826119f7565b6110328282611ad9565b7fcee92923a0c63eca6fc0402d78c9efde9f9f3dc73e6f9e14501bf734ed77f100546001600160a01b0316336001600160a01b03161461081257604051630d175fff60e31b8152336004820152602401610dd3565b5f805160206146f183398151915261103261120e611918565b5f805160206146b18339815191525460038401919085611b33565b6001600160a01b0381166112525760405163b20f76e360e01b81525f6004820152602401610dd3565b7fcee92923a0c63eca6fc0402d78c9efde9f9f3dc73e6f9e14501bf734ed77f10055565b5f805f806112848686611b3f565b9250925092506112948282611b88565b5090949350505050565b5f6112aa848484611c40565b90505b9392505050565b6110328282611ca1565b6112d1836112cb84611cea565b83611d16565b610abc57604051638baa579f60e01b815260040160405180910390fd5b6110328282611d86565b6106a681611ddc565b8151158015906113195750611317838383611e10565b155b15610abc57604051638baa579f60e01b815260040160405180910390fd5b6110328282611ea8565b5f5f805160206147118339815191526112ad7f3b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e0284612131565b61138383612152565b61138d8383611ea8565b6001600160a01b03811615610abc576113a683826119f7565b610abc8382611ad9565b5f805160206146f18339815191526110326113c9611918565b5f805160206146b183398151915254600384019190856122f1565b61103282826122fd565b6106a681612336565b5f5f805160206146f18339815191526114307f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db0388612131565b8061145957506001600160a01b0385165f90815260058201602052604090206114599088612131565b61147657604051631e32107b60e31b815260040160405180910390fd5b61148188868961235a565b61149e576040516322d3f3fb60e01b815260040160405180910390fd5b6114a6611918565b65ffffffffffff166114c35f805160206146b18339815191525490565b6114cd908a6143a6565b65ffffffffffff1610156114f457604051634be9cd8560e11b815260040160405180910390fd5b5f876001600160a01b031663b13442716040518163ffffffff1660e01b8152600401602060405180830381865afa158015611531573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611555919061432d565b90506001600160a01b03811661157e57604051633c1f615d60e21b815260040160405180910390fd5b5f816001600160a01b031663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115df91906143c4565b90506001600160401b0381166116b657816001600160a01b031663021a81568989898e8a6040518663ffffffff1660e01b81526004016116239594939291906143fe565b6020604051808303815f875af115801561163f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116639190614438565b604080516001600160a01b038c168152602081018b90529081018290529094507fa455bb45e23ed02807f6ef41727a47f3fcc85c9df0baa3570fd388f95b09b4da906060015b60405180910390a161179e565b5f196001600160401b0382160161178557816001600160a01b031663545ce3898989898e8a6040518663ffffffff1660e01b81526004016116fb9594939291906143fe565b6020604051808303815f875af1158015611717573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061173b9190614438565b604080516001600160a01b038c168152602081018b90529081018290529094507f4df99d47392012b66d459ea8fe495a8ce499b8faee622119c4cf353023b582fe906060016116a9565b60405163539cea7160e11b815260040160405180910390fd5b5050509695505050505050565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060915f80516020614731833981519152916117e99061444f565b80601f01602080910402602001604051908101604052809291908181526020018280546118159061444f565b80156118605780601f1061183757610100808354040283529160200191611860565b820191905f5260205f20905b81548152906001019060200180831161184357829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10380546060915f80516020614731833981519152916117e99061444f565b6106a681612376565b5f805160206146f18339815191526110326118cb611918565b6003830190846123aa565b60605f6118e384846123b5565b949350505050565b5f805160206146f1833981519152611902826124a3565b61103261190d611918565b600383019084612821565b5f610e8d61282c565b5f80858154811061193457611934614374565b905f5260205f20906003020160020160149054906101000a900460ff161561196f5760405163261e57c360e11b815260040160405180910390fd5b61197b85858585612836565b61073b858561292b565b5f80868154811061199857611998614374565b5f91825260208083206003929092029091016002810154604080516001600160a01b039092168285015280518083039094018452908101905292506119dc90610971565b8254909150610bd89065ffffffffffff168288888888612a4e565b6014611a0283612c87565b10611a20576040516372f2c48d60e11b815260040160405180910390fd5b806001600160a01b031663ce9b79306040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a80919061432d565b6040516323f752d560e01b81525f60048201525f1960248201526001600160a01b0391909116906323f752d5906044015f604051808303815f87803b158015611ac7575f80fd5b505af1158015610a7a573d5f803e3d5ffd5b5f805160206146f1833981519152611af0826124a3565b611afa8383612cd5565b611b25611b05611918565b6001600160a01b0385165f90815260058401602052604090209084612821565b610803600682018385612e48565b61080384848484612e60565b5f805f8351604103611b76576020840151604085015160608601515f1a611b6888828585612ef7565b955095509550505050611b81565b505081515f91506002905b9250925092565b5f826003811115611b9b57611b9b6143ea565b03611ba4575050565b6001826003811115611bb857611bb86143ea565b03611bd65760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115611bea57611bea6143ea565b03611c0b5760405163fce698f760e01b815260048101829052602401610dd3565b6003826003811115611c1f57611c1f6143ea565b03611032576040516335e2f38360e21b815260048101829052602401610dd3565b6001600160a01b0381165f908152600184016020526040812054801580159061073b575061073b8486611c74600185614487565b81548110611c8457611c84614374565b905f5260205f209060020201600101612fbf90919063ffffffff16565b5f805160206146f1833981519152610abc611cba611918565b5f805160206146b1833981519152546001600160a01b0386165f9081526005850160205260409020919085611b33565b5f6106d9611cf661300c565b8360405161190160f01b8152600281019290925260228201526042902090565b5f836001600160a01b03163b5f03611d74575f80611d348585611b3f565b5090925090505f816003811115611d4d57611d4d6143ea565b148015611d6b5750856001600160a01b0316826001600160a01b0316145b925050506112ad565b611d7f848484613015565b90506112ad565b5f805160206146f1833981519152611dcf611d9f611918565b5f805160206146b1833981519152546001600160a01b0386165f90815260058501602052604090209190856122f1565b61080360068201836130ec565b5f80516020614711833981519152611032611df5611918565b5f805160206146b18339815191525460028401919085611b33565b5f8083806020019051810190611e26919061432d565b6040516001600160601b0319606088811b8216602084015283901b1660348201529091505f906048016040516020818303038152906040528051906020012090505f611e7282866106cb565b9050826001600160a01b0316816001600160a01b0316148015611e9d57506001600160a01b03811615155b979650505050505050565b5f5f8051602061475183398151915290505f82806020019051810190611ece919061432d565b90505f611ed9611918565b6001600160a01b038381165f9081526001860160205260409020549192501615611f16576040516325aff6d160e21b815260040160405180910390fd5b6001600160a01b03821615801590611f565750611f3460018061449a565b6001600160a01b0386165f908152602085905260409020611f5490613100565b115b15611f7457604051639832bab160e01b815260040160405180910390fd5b6001600160a01b0385165f908152602084905260408120611f9490613100565b11156120c8576001600160a01b0385165f90815260208490526040812080548290611fc157611fc1614374565b5f9182526020909120600290910201546001600160a01b0316905061201482611ff55f805160206146b18339815191525490565b6001600160a01b0389165f908152602088905260409020919084613109565b1561207d57612051826120325f805160206146b18339815191525490565b6001600160a01b0389165f9081526020889052604090209190846122f1565b6001600160a01b0381165f908152600185016020526040902080546001600160a01b03191690556120c6565b6001600160a01b0386165f90815260208590526040902061209f90838361129e565b156120c6576001600160a01b0386165f9081526020859052604090206120c69083836123aa565b505b6001600160a01b038216156108da576001600160a01b0385165f9081526020849052604090206120f9908284612821565b6001600160a01b038083165f908152600185016020526040902080549187166001600160a01b03199092169190911790555050505050565b6001600160a01b0381165f90815260018301602052604081205415156106d6565b61215a613172565b6040516302910f8b60e31b81526001600160a01b03838116600483015291909116906314887c5890602401602060405180830381865afa1580156121a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121c491906144ad565b6121e157604051631f0853c160e21b815260040160405180910390fd5b7f3b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e01546001600160a01b03166001600160a01b031663220d32d4826122437f779150488f5e984d1f840ba606e388ada6c73b44f261274c3595c61a30023e005490565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa15801561228c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122b091906144ad565b6122cd57604051634d1cc09f60e11b815260040160405180910390fd5b5f805160206147118339815191526110326122e6611918565b600283019084612821565b61080384848484613193565b5f805160206146f1833981519152610abc612316611918565b6001600160a01b0385165f908152600584016020526040902090846123aa565b5f8051602061471183398151915261103261234f611918565b6002830190846123aa565b5f61236584836133fb565b806112aa57506112aa848484613435565b5f8051602061471183398151915261103261238f611918565b5f805160206146b183398151915254600284019190856122f1565b610abc838383613485565b8154606090806001600160401b038111156123d2576123d2613c92565b6040519080825280602002602001820160405280156123fb578160200160208202803683370190505b5091505f805b828110156124995761242185875f018381548110611c8457611c84614374565b1561249157855f01818154811061243a5761243a614374565b5f9182526020909120600290910201546001600160a01b0316848361245e8161435c565b94508151811061247057612470614374565b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101612401565b5082525092915050565b5f805160206146f18339815191526124b9613518565b6040516302910f8b60e31b81526001600160a01b03848116600483015291909116906314887c5890602401602060405180830381865afa1580156124ff573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061252391906144ad565b612540576040516362df054560e01b815260040160405180910390fd5b816001600160a01b031663392e53cd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561257c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125a091906144ad565b6125bd57604051639a09fd8760e01b815260040160405180910390fd5b6125ca600682018361352d565b806125dd57506125dd6003820183612131565b156125fb576040516324ec133760e11b815260040160405180910390fd5b5f826001600160a01b0316634ff0876a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612638573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061265c91906144cc565b90505f836001600160a01b031663b13442716040518163ffffffff1660e01b8152600401602060405180830381865afa15801561269b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126bf919061432d565b90506001600160a01b038116156127e2575f816001600160a01b031663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561270d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061273191906143c4565b90505f196001600160401b038216016127b557816001600160a01b031663e054e08b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612780573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127a491906144cc565b6127ae9084614388565b92506127e0565b60016001600160401b03821611156127e05760405163539cea7160e11b815260040160405180910390fd5b505b5f805160206146b18339815191525465ffffffffffff168265ffffffffffff1610156108035760405163121f507960e11b815260040160405180910390fd5b610abc838383613541565b5f610e8d426135f4565b5f80858154811061284957612849614374565b905f5260205f20906003020190505f6128bc7f9d6222a9cceb0fe2dde310f8edcb19b0830b29f25b1550c13fb346905164f82287876040516020016128a1939291909283526020830191909152604082015260600190565b60405160208183030381529060405280519060200120611cea565b6002830154604080516020601f880181900481028201810190925286815292935061290e926001600160a01b0390921691849188908890819084018382808284375f92019190915250611d1692505050565b610a7a57604051638baa579f60e01b815260040160405180910390fd5b5f805f848154811061293f5761293f614374565b5f9182526020822060016003909202010154915061295e6002856145ca565b9050818103612972576001925050506106d9565b818110156129e1575f6129858284614487565b90505f600261299587600161449a565b61299f91906145ca565b90505f8482116129b8576129b38286614487565b6129c2565b6129c28583614487565b90508083116129d9576001955050505050506106d9565b505050612a44565b5f6129ec8383614487565b90505f60026129fc600188614487565b612a0691906145ca565b90505f848211612a1f57612a1a8286614487565b612a29565b612a298583614487565b9050808311612a40576001955050505050506106d9565b5050505b505f949350505050565b5f612a59878761362a565b80519091508483141580612a6d5750848114155b15612a8b576040516351c4859160e01b815260040160405180910390fd5b5f612adc5f612ab87f779150488f5e984d1f840ba606e388ada6c73b44f261274c3595c61a30023e005490565b6001600160601b031960609190911b166bffffffffffffffffffffffff9091161790565b90505f5b82811015612c7b575f848281518110612afb57612afb614374565b602002602001015190505f816001600160a01b031663ce9b79306040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b66919061432d565b6001600160a01b031663e02f6937858d8f8e8e89818110612b8957612b89614374565b9050602002810190612b9b91906145d8565b6040518663ffffffff1660e01b8152600401612bbb95949392919061461a565b602060405180830381865afa158015612bd6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bfa9190614438565b9050805f03612c0a575050612c73565b612c6f8c83868e858d8d8a818110612c2457612c24614374565b9050602002810190612c3691906145d8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506113f792505050565b5050505b600101612ae0565b50505050505050505050565b6001600160a01b0381165f9081527f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db05602052604081205f805160206146f1833981519152906112ad90613100565b5f816001600160a01b031663ce9b79306040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d12573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d36919061432d565b905060026001600160401b0316816001600160a01b031663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d7f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da391906143c4565b6001600160401b0316141580612e2a5750826001600160a01b0316816001600160a01b031663570ca7356040518163ffffffff1660e01b8152600401602060405180830381865afa158015612dfa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e1e919061432d565b6001600160a01b031614155b15610abc57604051634e4f76bb60e11b815260040160405180910390fd5b5f6112aa846001600160a01b038086169085166137a7565b6001600160a01b0381165f9081526001850160205260408120549003612e995760405163aba4733960e01b815260040160405180910390fd5b6001600160a01b0381165f908152600180860160205260409091205461080391859185918891612ec99190614487565b81548110612ed957612ed9614374565b905f5260205f2090600202016001016137c39092919063ffffffff16565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115612f3057505f91506003905082612fb5565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612f81573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116612fac57505f925060019150829050612fb5565b92505f91508190505b9450945094915050565b81545f9065ffffffffffff80841691161080156106d657508254600160301b900465ffffffffffff1615806106d6575050905465ffffffffffff918216600160301b909104909116101590565b5f610e8d61384e565b5f805f856001600160a01b0316858560405160240161303592919061466f565b60408051601f198184030181529181526020820180516001600160e01b0316630b135d3f60e11b1790525161306a9190613c4d565b5f60405180830381855afa9150503d805f81146130a2576040519150601f19603f3d011682016040523d82523d5f602084013e6130a7565b606091505b50915091508180156130bb57506020815110155b80156130e257508051630b135d3f60e11b906130e09083016020908101908401614438565b145b9695505050505050565b5f6106d6836001600160a01b0384166138c1565b5f6106d9825490565b6001600160a01b0381165f908152600185016020526040812054808203613133575f9150506118e3565b6130e2858588613144600186614487565b8154811061315457613154614374565b905f5260205f2090600202016001016138dd9092919063ffffffff16565b5f805f805160206147118339815191525b546001600160a01b031692915050565b6001600160a01b0381165f908152600185016020526040812054908190036131ce5760405163aba4733960e01b815260040160405180910390fd5b806131d881614687565b9150506132128484875f0184815481106131f4576131f4614374565b905f5260205f20906002020160010161393e9092919063ffffffff16565b61321d81600161449a565b855411613289576001600160a01b0382165f908152600186016020526040812055845485908061324f5761324f61469c565b5f8281526020902060025f199092019182020180546001600160a01b031916815560010180546001600160601b0319169055905550610803565b8454859061329990600190614487565b815481106132a9576132a9614374565b905f5260205f209060020201855f0182815481106132c9576132c9614374565b5f9182526020909120825460029092020180546001600160a01b0319166001600160a01b039092169190911781556001918201805492909101805465ffffffffffff19811665ffffffffffff94851690811783559254600160301b908190049094169093026001600160601b031990931690911791909117905584548590806133545761335461469c565b5f828152602080822060025f199094019384020180546001600160a01b0319168155600190810180546001600160601b0319169055929093556001600160a01b038516815287820190925260408220919091556133b290829061449a565b856001015f875f0184815481106133cb576133cb614374565b5f91825260208083206002909202909101546001600160a01b031683528201929092526040019020555050505050565b5f5f805160206146f18339815191526118e37f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db03858561129e565b6001600160a01b0382165f9081527f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db05602052604081205f805160206146f18339815191529061073b90868561129e565b6001600160a01b0381165f90815260018401602052604081205490036134be5760405163aba4733960e01b815260040160405180910390fd5b6001600160a01b0381165f9081526001808501602052604090912054610abc91849186916134eb91614487565b815481106134fb576134fb614374565b905f5260205f2090600202016001016139c890919063ffffffff16565b5f805f805160206146f1833981519152613183565b5f6106d6836001600160a01b038416613a1b565b6001600160a01b0381165f9081526001840160205260409020541561357957604051630ea075bf60e21b815260040160405180910390fd5b8254600180820185555f85815260209020600290920290910180546001600160a01b0319166001600160a01b038416178155906135ce9082018481546001600160601b03191665ffffffffffff909116179055565b5082546001600160a01b039091165f908152600190930160205260409092209190915550565b5f65ffffffffffff821115613626576040516306dfcc6560e41b81526030600482015260248101839052604401610dd3565b5090565b60605f805160206146f18339815191525f6136657f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db03866118d6565b6001600160a01b0385165f90815260058401602052604081209192509061368c90876118d6565b82518151919250905f61369f828461449a565b6001600160401b038111156136b6576136b6613c92565b6040519080825280602002602001820160405280156136df578160200160208202803683370190505b5090505f5b83811015613738578581815181106136fe576136fe614374565b602002602001015182828151811061371857613718614374565b6001600160a01b03909216602092830291909101909101526001016136e4565b505f5b8281101561379a5784818151811061375557613755614374565b602002602001015182828661376a919061449a565b8151811061377a5761377a614374565b6001600160a01b039092166020928302919091019091015260010161373b565b5098975050505050505050565b5f82815260028401602052604081208290556112aa8484613a26565b825465ffffffffffff16156137eb57604051637952fbad60e11b815260040160405180910390fd5b825465ffffffffffff8084169161380b918491600160301b9004166143a6565b65ffffffffffff16111561383257604051631ba9803b60e11b815260040160405180910390fd5b5081546001600160601b03191665ffffffffffff909116179055565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f613878613a31565b613880613a99565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f81815260028301602052604081208190556106d68383613adb565b82545f9065ffffffffffff1615801561390557508354600160301b900465ffffffffffff1615155b80156112aa5750835465ffffffffffff8085169161392c918591600160301b9004166143a6565b65ffffffffffff161115949350505050565b825465ffffffffffff1615158061396357508254600160301b900465ffffffffffff16155b156139815760405163c0f9610560e01b815260040160405180910390fd5b825465ffffffffffff808416916139a1918491600160301b9004166143a6565b65ffffffffffff161115610abc57604051631ba9803b60e11b815260040160405180910390fd5b8154600160301b900465ffffffffffff16156139f757604051633f54562b60e11b815260040160405180910390fd5b815465ffffffffffff91909116600160301b026001600160601b0319909116179055565b5f6106d68383613ae6565b5f6106d68383613afd565b5f5f8051602061473183398151915281613a496117ab565b805190915015613a6157805160209091012092915050565b81548015613a70579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b5f5f8051602061473183398151915281613ab161186b565b805190915015613ac957805160209091012092915050565b60018201548015613a70579392505050565b5f6106d68383613b49565b5f81815260018301602052604081205415156106d6565b5f818152600183016020526040812054613b4257508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106d9565b505f6106d9565b5f8181526001830160205260408120548015613c23575f613b6b600183614487565b85549091505f90613b7e90600190614487565b9050808214613bdd575f865f018281548110613b9c57613b9c614374565b905f5260205f200154905080875f018481548110613bbc57613bbc614374565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613bee57613bee61469c565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506106d9565b5f9150506106d9565b8284823760609190911b6001600160601b0319169101908152601401919050565b5f82518060208501845e5f920191825250919050565b6001600160a01b03811681146106a6575f80fd5b5f60208284031215613c87575f80fd5b81356112ad81613c63565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112613cb5575f80fd5b81356001600160401b03811115613cce57613cce613c92565b604051601f8201601f19908116603f011681016001600160401b0381118282101715613cfc57613cfc613c92565b604052818152838201602001851015613d13575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613d40575f80fd5b8235915060208301356001600160401b03811115613d5c575f80fd5b613d6885828601613ca6565b9150509250929050565b65ffffffffffff811681146106a6575f80fd5b5f8060408385031215613d96575f80fd5b8235613da181613d72565b915060208301356001600160401b03811115613d5c575f80fd5b5f805f60608486031215613dcd575f80fd5b8335613dd881613c63565b92506020840135613de881613c63565b915060408401356001600160401b03811115613e02575f80fd5b613e0e86828701613ca6565b9150509250925092565b5f805f8060808587031215613e2b575f80fd5b8435613e3681613c63565b935060208501356001600160401b03811115613e50575f80fd5b613e5c87828801613ca6565b93505060408501356001600160401b03811115613e77575f80fd5b613e8387828801613ca6565b92505060608501356001600160401b03811115613e9e575f80fd5b613eaa87828801613ca6565b91505092959194509250565b5f60208284031215613ec6575f80fd5b81356001600160401b03811115613edb575f80fd5b6118e384828501613ca6565b5f805f805f60a08688031215613efb575f80fd5b8535613f0681613c63565b945060208601356001600160401b03811115613f20575f80fd5b613f2c88828901613ca6565b9450506040860135613f3d81613c63565b925060608601356001600160401b03811115613f57575f80fd5b613f6388828901613ca6565b92505060808601356001600160401b03811115613f7e575f80fd5b613f8a88828901613ca6565b9150509295509295909350565b5f805f60608486031215613fa9575f80fd5b83356001600160401b03811115613fbe575f80fd5b613fca86828701613ca6565b9350506020840135613de881613c63565b5f8060408385031215613fec575f80fd5b8235613da181613c63565b5f805f805f8060c0878903121561400c575f80fd5b863561401781613d72565b9550602087013561402781613c63565b945060408701359350606087013561403e81613c63565b92506080870135915060a08701356001600160401b0381111561405f575f80fd5b61406b89828a01613ca6565b9150509295509295509295565b5f8060408385031215614089575f80fd5b82359150602083013561409b81613c63565b809150509250929050565b5f80604083850312156140b7575f80fd5b82356140c281613c63565b946020939093013593505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f61411c60e08301896140d0565b828103604084015261412e81896140d0565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015614183578351835260209384019390920191600101614165565b50909b9a5050505050505050505050565b5f602082840312156141a4575f80fd5b5035919050565b602081525f6106d660208301846140d0565b5f80604083850312156141ce575f80fd5b82356001600160401b038111156141e3575f80fd5b6141ef85828601613ca6565b92505060208301356001600160401b03811115613d5c575f80fd5b5f8083601f84011261421a575f80fd5b5081356001600160401b03811115614230575f80fd5b6020830191508360208260051b850101111561424a575f80fd5b9250929050565b5f805f805f805f8060a0898b031215614268575f80fd5b883597506020890135965060408901356001600160401b0381111561428b575f80fd5b8901601f81018b1361429b575f80fd5b80356001600160401b038111156142b0575f80fd5b8b60208284010111156142c1575f80fd5b6020919091019650945060608901356001600160401b038111156142e3575f80fd5b6142ef8b828c0161420a565b90955093505060808901356001600160401b0381111561430d575f80fd5b6143198b828c0161420a565b999c989b5096995094979396929594505050565b5f6020828403121561433d575f80fd5b81516112ad81613c63565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161436d5761436d614348565b5060010190565b634e487b7160e01b5f52603260045260245ffd5b65ffffffffffff82811682821603908111156106d9576106d9614348565b65ffffffffffff81811683821601908111156106d9576106d9614348565b5f602082840312156143d4575f80fd5b81516001600160401b03811681146112ad575f80fd5b634e487b7160e01b5f52602160045260245ffd5b85815260018060a01b038516602082015283604082015265ffffffffffff8316606082015260a060808201525f611e9d60a08301846140d0565b5f60208284031215614448575f80fd5b5051919050565b600181811c9082168061446357607f821691505b60208210810361448157634e487b7160e01b5f52602260045260245ffd5b50919050565b818103818111156106d9576106d9614348565b808201808211156106d9576106d9614348565b5f602082840312156144bd575f80fd5b815180151581146112ad575f80fd5b5f602082840312156144dc575f80fd5b81516112ad81613d72565b6001815b60018411156145225780850481111561450657614506614348565b600184161561451457908102905b60019390931c9280026144eb565b935093915050565b5f82614538575060016106d9565b8161454457505f6106d9565b816001811461455a576002811461456457614580565b60019150506106d9565b60ff84111561457557614575614348565b50506001821b6106d9565b5060208310610133831016604e8410600b84101617156145a3575081810a6106d9565b6145af5f1984846144e7565b805f19048211156145c2576145c2614348565b029392505050565b5f6106d660ff84168361452a565b5f808335601e198436030181126145ed575f80fd5b8301803591506001600160401b03821115614606575f80fd5b60200191503681900382131561424a575f80fd5b8581526001600160a01b038516602082015265ffffffffffff841660408201526080606082018190528101829052818360a08301375f81830160a090810191909152601f909201601f19160101949350505050565b828152604060208201525f6112aa60408301846140d0565b5f8161469557614695614348565b505f190190565b634e487b7160e01b5f52603160045260245ffdfe52becd5b30d67421b1f63b9d90d513daf82b3973912d3edfdac9468c1743c0007c1bcd600c3fcfbc53470fac03a90d5cf6aa7b77c3f1ed10e6c6bd4d192eaf00485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db003b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e00a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1003da47716e6090d5a5545e03387f4dac112d37cd069a5573bb81de8579bd9dc00a2646970667358221220efba82b0262fa824f848cbf709f95c96f9891078d81449b0f6c97c04b0e9396a64736f6c634300081a00330000000000000000000000007d03b7343bf8d5cec7c0c27ece084a20113d15c900000000000000000000000000000000000000000000000000000000000151800000000000000000000000006f75a4fff97326a00e52662d82ea4fde86a2c548000000000000000000000000407a039d94948484d356efb765b3c74382a050b400000000000000000000000058973d16ffa900d11fc22e5e2b6840d9f7e1340100000000000000000000000094fe567e412fc828aa3403403c7b980de2713b2100000000000000000000000068e7df0a38467cb511c6ce43bded70f202a0b8f6
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061027d575f3560e01c806369f83e4b1161015a5780639c99bd75116100cc578063c84cde4411610085578063c84cde441461061e578063c9584f6214610631578063ca2d2a1814610644578063ce8c187014610657578063db3adf121461066a578063f81d58ff146106895761027d565b80639c99bd751461035c578063a876b89a146105d0578063b1630faa146105d8578063b18125be146105eb578063b38de8b41461060b578063c3778f161461035c5761027d565b80637ecebe001161011e5780637ecebe001461051a57806384af63241461054e57806384b0196e146105615780638bd872ab1461035c5780638d9776721461057c5780638da5cb5b146105c85761027d565b806369f83e4b146104c65780636d408712146104d9578063715018a6146104ec5780637664c514146104f457806377451229146105075761027d565b8063348d6335116101f357806347bab83d116101b757806347bab83d146104855780634afdcbde146104985780635210ca021461035c57806354b0116b146104a05780635b2191fa146104b35780635d991c961461035c5761027d565b8063348d6335146104265780633e030fab146104395780633e1ad83f1461044c578063458cc5421461045f57806347449640146104725761027d565b806319045a251161024557806319045a25146103aa5780631e0f2e1f146103d5578063292a8a9b146103f85780633280779e1461040b578063329685571461035c57806332e9181e1461041e5761027d565b806303426e7a1461033457806308e809f0146103495780630a0530ea1461035c57806313af4035146103815780631451178814610394575b5f7ffd87879bc98f37af7578af722aecfbe5843e5ad354da2d1e70cb5157c4ec88005490505f80826001600160a01b03165f36306040516020016102c393929190613c2c565b60408051601f19818403018152908290526102dd91613c4d565b5f60405180830381855af49150503d805f8114610315576040519150601f19603f3d011682016040523d82523d5f602084013e61031a565b606091505b50915091508161032c57805160208201fd5b805160208201f35b610347610342366004613c77565b61069c565b005b610347610357366004613c77565b6106a9565b610364600181565b6040516001600160401b0390911681526020015b60405180910390f35b61034761038f366004613c77565b6106ba565b61039c601481565b604051908152602001610378565b6103bd6103b8366004613d2f565b6106cb565b6040516001600160a01b039091168152602001610378565b6103e86103e3366004613d85565b6106df565b6040519015158152602001610378565b610347610406366004613c77565b610744565b610347610419366004613dbb565b61074e565b610347610809565b610347610434366004613e18565b610814565b610347610447366004613dbb565b6108e1565b6103bd61045a366004613eb6565b610971565b61034761046d366004613ee7565b6109bf565b610347610480366004613c77565b610a82565b610347610493366004613c77565b610a93565b610347610a9d565b6103476104ae366004613f97565b610aa6565b6103476104c1366004613fdb565b610ac1565b6103476104d4366004613dbb565b610b58565b6103476104e7366004613ff7565b610bc2565b610347610be1565b610347610502366004613c77565b610bf2565b61039c610515366004614078565b610bfc565b61039c610528366004613c77565b6001600160a01b03165f9081525f805160206146d1833981519152602052604090205490565b61039c61055c3660046140a6565b919050565b610569610d68565b60405161037897969594939291906140fe565b61058f61058a366004614194565b610e16565b6040805165ffffffffffff909516855260208501939093526001600160a01b039091169183019190915215156060820152608001610378565b6103bd610e64565b610347610e92565b6103476105e6366004613c77565b610e9b565b6105fe6105f9366004613c77565b610eac565b60405161037891906141ab565b610347610619366004613dbb565b610f4c565b61034761062c366004613fdb565b610fb6565b61034761063f3660046141bd565b61101d565b610347610652366004613c77565b611036565b610347610665366004613fdb565b611047565b6106726110ae565b60405165ffffffffffff9091168152602001610378565b6103e8610697366004614251565b6110c3565b6106a63382611166565b50565b6106b16111a0565b6106a6816111f5565b6106c26111a0565b6106a681611229565b5f6106d68383611276565b90505b92915050565b5f805f8051602061475183398151915290505f83806020019051810190610706919061432d565b6001600160a01b038082165f90815260018501602090815260408083205490931682528590522090915061073b90868361129e565b95945050505050565b6106a633826112b4565b6001600160a01b0383165f9081525f805160206146d1833981519152602081905260408220805491926107f99287927f3f13cbea81d7441d3504384770639bed665f2fdd45100939f9d93abca2708a02928492899290916107ae8361435c565b909155506040805160208101959095526001600160a01b039384169085015291166060830152608082015260a0015b60405160208183030381529060405280519060200120846112be565b61080384846112ee565b50505050565b610812336112f8565b565b61081f848483611301565b82516020808501919091206001600160a01b0386165f9081525f805160206146d1833981519152928390526040812080546108d09389937f1a8c1411ba00c3d249f48c949873f9596d266a13be61f3bc73c9e40f8bf470ba938593916108848361435c565b909155506040805160208101959095526001600160a01b03909316928401929092526060830152608082015260a0015b60405160208183030381529060405280519060200120856112be565b6108da8585611337565b5050505050565b6108ea83611341565b610907576040516325ec6c1f60e01b815260040160405180910390fd5b6001600160a01b0383165f9081525f805160206146d1833981519152602081905260408220805491926109679287927f616558fa4c156951628ff577e43a2ffbe2624ffe99f75a9f57c50a310530064d928492899290916107ae8361435c565b6108038484611166565b5f805f805160206147518339815191529050806001015f8480602001905181019061099c919061432d565b6001600160a01b03908116825260208201929092526040015f2054169392505050565b6109ca858583611301565b83516020808601919091206001600160a01b0387165f9081525f805160206146d183398151915292839052604081208054610a6f938a937f28e2348304d9c105deffd086bc056c631de89c293d37fe5623eae873d82969cc9385938b92909190610a338361435c565b909155506040805160208101969096526001600160a01b03948516908601526060850192909252909116608083015260a082015260c0016108b4565b610a7a86868661137a565b505050505050565b610a8a6111a0565b6106a6816113b0565b6106a633826113e4565b610812336113ee565b610ab1338483611301565b610abc33848461137a565b505050565b6001600160a01b0382165f9081525f805160206146d183398151915260208190526040822080549192610b4f9286927ff4b5ceebc7b665a989c88fb1987d90ecaa1646a6f4a3d02f7c33434f68567a029284929190610b1f8361435c565b919050556040516020016107dd939291909283526001600160a01b03919091166020830152604082015260600190565b610abc836113ee565b6001600160a01b0383165f9081525f805160206146d183398151915260208190526040822080549192610bb89287927f40ca710eba568c6bc31e352337f7e0f89b32dce800b1156ccb725edf2d15adc6928492899290916107ae8361435c565b61080384846113e4565b610bca6111a0565b610bd88686868686866113f7565b50505050505050565b610be96111a0565b6108125f611229565b6106a633826112ee565b604080516001600160a01b03831660208201525f9182910160405160208183030381529060405290505f610c2f82610971565b9050610c42610c3c6110ae565b836106df565b610c5f5760405163754e047b60e11b815260040160405180910390fd5b610c6881611341565b610c85576040516325ec6c1f60e01b815260040160405180910390fd5b5f8054905092505f6040518060800160405280610ca06110ae565b65ffffffffffff908116825260208083018a90526001600160a01b03808a1660408086018290525f6060968701819052885460018181018b55998252858220895160039092020180549190971665ffffffffffff199091161786559387015197850197909755858701516002909401805496909501511515600160a01b026001600160a81b0319909616939091169290921793909317909155915185917fb250fc64dc0fe8dc601cf62d8a1e52cd0827cbf95d4585c8117c95567740d12891a3505092915050565b5f60608082808083815f805160206147318339815191528054909150158015610d9357506001810154155b610ddc5760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b60448201526064015b60405180910390fd5b610de46117ab565b610dec61186b565b604080515f80825260208201909252600f60f81b9c939b5091995046985030975095509350915050565b5f8181548110610e24575f80fd5b5f91825260209091206003909102018054600182015460029092015465ffffffffffff90911692506001600160a01b03811690600160a01b900460ff1684565b5f610e8d7fcee92923a0c63eca6fc0402d78c9efde9f9f3dc73e6f9e14501bf734ed77f1005490565b905090565b610812336118a9565b610ea36111a0565b6106a6816118b2565b60605f805160206147518339815191525f610ee5610ec86110ae565b6001600160a01b0386165f908152602085905260409020906118d6565b905080515f03610f1357604080515f6020820152015b60405160208183030381529060405292505050919050565b805f81518110610f2557610f25614374565b6020026020010151604051602001610efb91906001600160a01b0391909116815260200190565b6001600160a01b0383165f9081525f805160206146d183398151915260208190526040822080549192610fac9287927ff8c72a3aa921e817ca53424f4d187362d26d249fdcee703fee36ad92b9142771928492899290916107ae8361435c565b61080384846112b4565b6001600160a01b0382165f9081525f805160206146d1833981519152602081905260408220805491926110149286927f49584bafbd77382376a35a9d49efaacece2be43b76c8e96aff93c9b6742410719284929190610b1f8361435c565b610abc836112f8565b611028338383611301565b6110323383611337565b5050565b61103e6111a0565b6106a6816118eb565b6001600160a01b0382165f9081525f805160206146d1833981519152602081905260408220805491926110a59286927ffebeac2fb9f2c5f3e90991eb339385576ae705aa0dd905a9f965f8b76ba598409284929190610b1f8361435c565b610abc836118a9565b5f60016110b9611918565b610e8d9190614388565b5f6110d089898989611921565b905060015f8a815481106110e6576110e6614374565b905f5260205f20906003020160020160146101000a81548160ff0219169083151502179055508061111e5761111e8986868686611985565b887fa4a1d94d1676fe30c56127e96641c5e95021748f1e6b8271009dde8177cc2ab482604051611152911515815260200190565b60405180910390a298975050505050505050565b61116f82611341565b61118c576040516325ec6c1f60e01b815260040160405180910390fd5b61119682826119f7565b6110328282611ad9565b7fcee92923a0c63eca6fc0402d78c9efde9f9f3dc73e6f9e14501bf734ed77f100546001600160a01b0316336001600160a01b03161461081257604051630d175fff60e31b8152336004820152602401610dd3565b5f805160206146f183398151915261103261120e611918565b5f805160206146b18339815191525460038401919085611b33565b6001600160a01b0381166112525760405163b20f76e360e01b81525f6004820152602401610dd3565b7fcee92923a0c63eca6fc0402d78c9efde9f9f3dc73e6f9e14501bf734ed77f10055565b5f805f806112848686611b3f565b9250925092506112948282611b88565b5090949350505050565b5f6112aa848484611c40565b90505b9392505050565b6110328282611ca1565b6112d1836112cb84611cea565b83611d16565b610abc57604051638baa579f60e01b815260040160405180910390fd5b6110328282611d86565b6106a681611ddc565b8151158015906113195750611317838383611e10565b155b15610abc57604051638baa579f60e01b815260040160405180910390fd5b6110328282611ea8565b5f5f805160206147118339815191526112ad7f3b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e0284612131565b61138383612152565b61138d8383611ea8565b6001600160a01b03811615610abc576113a683826119f7565b610abc8382611ad9565b5f805160206146f18339815191526110326113c9611918565b5f805160206146b183398151915254600384019190856122f1565b61103282826122fd565b6106a681612336565b5f5f805160206146f18339815191526114307f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db0388612131565b8061145957506001600160a01b0385165f90815260058201602052604090206114599088612131565b61147657604051631e32107b60e31b815260040160405180910390fd5b61148188868961235a565b61149e576040516322d3f3fb60e01b815260040160405180910390fd5b6114a6611918565b65ffffffffffff166114c35f805160206146b18339815191525490565b6114cd908a6143a6565b65ffffffffffff1610156114f457604051634be9cd8560e11b815260040160405180910390fd5b5f876001600160a01b031663b13442716040518163ffffffff1660e01b8152600401602060405180830381865afa158015611531573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611555919061432d565b90506001600160a01b03811661157e57604051633c1f615d60e21b815260040160405180910390fd5b5f816001600160a01b031663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115df91906143c4565b90506001600160401b0381166116b657816001600160a01b031663021a81568989898e8a6040518663ffffffff1660e01b81526004016116239594939291906143fe565b6020604051808303815f875af115801561163f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116639190614438565b604080516001600160a01b038c168152602081018b90529081018290529094507fa455bb45e23ed02807f6ef41727a47f3fcc85c9df0baa3570fd388f95b09b4da906060015b60405180910390a161179e565b5f196001600160401b0382160161178557816001600160a01b031663545ce3898989898e8a6040518663ffffffff1660e01b81526004016116fb9594939291906143fe565b6020604051808303815f875af1158015611717573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061173b9190614438565b604080516001600160a01b038c168152602081018b90529081018290529094507f4df99d47392012b66d459ea8fe495a8ce499b8faee622119c4cf353023b582fe906060016116a9565b60405163539cea7160e11b815260040160405180910390fd5b5050509695505050505050565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060915f80516020614731833981519152916117e99061444f565b80601f01602080910402602001604051908101604052809291908181526020018280546118159061444f565b80156118605780601f1061183757610100808354040283529160200191611860565b820191905f5260205f20905b81548152906001019060200180831161184357829003601f168201915b505050505091505090565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10380546060915f80516020614731833981519152916117e99061444f565b6106a681612376565b5f805160206146f18339815191526110326118cb611918565b6003830190846123aa565b60605f6118e384846123b5565b949350505050565b5f805160206146f1833981519152611902826124a3565b61103261190d611918565b600383019084612821565b5f610e8d61282c565b5f80858154811061193457611934614374565b905f5260205f20906003020160020160149054906101000a900460ff161561196f5760405163261e57c360e11b815260040160405180910390fd5b61197b85858585612836565b61073b858561292b565b5f80868154811061199857611998614374565b5f91825260208083206003929092029091016002810154604080516001600160a01b039092168285015280518083039094018452908101905292506119dc90610971565b8254909150610bd89065ffffffffffff168288888888612a4e565b6014611a0283612c87565b10611a20576040516372f2c48d60e11b815260040160405180910390fd5b806001600160a01b031663ce9b79306040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a80919061432d565b6040516323f752d560e01b81525f60048201525f1960248201526001600160a01b0391909116906323f752d5906044015f604051808303815f87803b158015611ac7575f80fd5b505af1158015610a7a573d5f803e3d5ffd5b5f805160206146f1833981519152611af0826124a3565b611afa8383612cd5565b611b25611b05611918565b6001600160a01b0385165f90815260058401602052604090209084612821565b610803600682018385612e48565b61080384848484612e60565b5f805f8351604103611b76576020840151604085015160608601515f1a611b6888828585612ef7565b955095509550505050611b81565b505081515f91506002905b9250925092565b5f826003811115611b9b57611b9b6143ea565b03611ba4575050565b6001826003811115611bb857611bb86143ea565b03611bd65760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115611bea57611bea6143ea565b03611c0b5760405163fce698f760e01b815260048101829052602401610dd3565b6003826003811115611c1f57611c1f6143ea565b03611032576040516335e2f38360e21b815260048101829052602401610dd3565b6001600160a01b0381165f908152600184016020526040812054801580159061073b575061073b8486611c74600185614487565b81548110611c8457611c84614374565b905f5260205f209060020201600101612fbf90919063ffffffff16565b5f805160206146f1833981519152610abc611cba611918565b5f805160206146b1833981519152546001600160a01b0386165f9081526005850160205260409020919085611b33565b5f6106d9611cf661300c565b8360405161190160f01b8152600281019290925260228201526042902090565b5f836001600160a01b03163b5f03611d74575f80611d348585611b3f565b5090925090505f816003811115611d4d57611d4d6143ea565b148015611d6b5750856001600160a01b0316826001600160a01b0316145b925050506112ad565b611d7f848484613015565b90506112ad565b5f805160206146f1833981519152611dcf611d9f611918565b5f805160206146b1833981519152546001600160a01b0386165f90815260058501602052604090209190856122f1565b61080360068201836130ec565b5f80516020614711833981519152611032611df5611918565b5f805160206146b18339815191525460028401919085611b33565b5f8083806020019051810190611e26919061432d565b6040516001600160601b0319606088811b8216602084015283901b1660348201529091505f906048016040516020818303038152906040528051906020012090505f611e7282866106cb565b9050826001600160a01b0316816001600160a01b0316148015611e9d57506001600160a01b03811615155b979650505050505050565b5f5f8051602061475183398151915290505f82806020019051810190611ece919061432d565b90505f611ed9611918565b6001600160a01b038381165f9081526001860160205260409020549192501615611f16576040516325aff6d160e21b815260040160405180910390fd5b6001600160a01b03821615801590611f565750611f3460018061449a565b6001600160a01b0386165f908152602085905260409020611f5490613100565b115b15611f7457604051639832bab160e01b815260040160405180910390fd5b6001600160a01b0385165f908152602084905260408120611f9490613100565b11156120c8576001600160a01b0385165f90815260208490526040812080548290611fc157611fc1614374565b5f9182526020909120600290910201546001600160a01b0316905061201482611ff55f805160206146b18339815191525490565b6001600160a01b0389165f908152602088905260409020919084613109565b1561207d57612051826120325f805160206146b18339815191525490565b6001600160a01b0389165f9081526020889052604090209190846122f1565b6001600160a01b0381165f908152600185016020526040902080546001600160a01b03191690556120c6565b6001600160a01b0386165f90815260208590526040902061209f90838361129e565b156120c6576001600160a01b0386165f9081526020859052604090206120c69083836123aa565b505b6001600160a01b038216156108da576001600160a01b0385165f9081526020849052604090206120f9908284612821565b6001600160a01b038083165f908152600185016020526040902080549187166001600160a01b03199092169190911790555050505050565b6001600160a01b0381165f90815260018301602052604081205415156106d6565b61215a613172565b6040516302910f8b60e31b81526001600160a01b03838116600483015291909116906314887c5890602401602060405180830381865afa1580156121a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121c491906144ad565b6121e157604051631f0853c160e21b815260040160405180910390fd5b7f3b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e01546001600160a01b03166001600160a01b031663220d32d4826122437f779150488f5e984d1f840ba606e388ada6c73b44f261274c3595c61a30023e005490565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa15801561228c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122b091906144ad565b6122cd57604051634d1cc09f60e11b815260040160405180910390fd5b5f805160206147118339815191526110326122e6611918565b600283019084612821565b61080384848484613193565b5f805160206146f1833981519152610abc612316611918565b6001600160a01b0385165f908152600584016020526040902090846123aa565b5f8051602061471183398151915261103261234f611918565b6002830190846123aa565b5f61236584836133fb565b806112aa57506112aa848484613435565b5f8051602061471183398151915261103261238f611918565b5f805160206146b183398151915254600284019190856122f1565b610abc838383613485565b8154606090806001600160401b038111156123d2576123d2613c92565b6040519080825280602002602001820160405280156123fb578160200160208202803683370190505b5091505f805b828110156124995761242185875f018381548110611c8457611c84614374565b1561249157855f01818154811061243a5761243a614374565b5f9182526020909120600290910201546001600160a01b0316848361245e8161435c565b94508151811061247057612470614374565b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101612401565b5082525092915050565b5f805160206146f18339815191526124b9613518565b6040516302910f8b60e31b81526001600160a01b03848116600483015291909116906314887c5890602401602060405180830381865afa1580156124ff573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061252391906144ad565b612540576040516362df054560e01b815260040160405180910390fd5b816001600160a01b031663392e53cd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561257c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125a091906144ad565b6125bd57604051639a09fd8760e01b815260040160405180910390fd5b6125ca600682018361352d565b806125dd57506125dd6003820183612131565b156125fb576040516324ec133760e11b815260040160405180910390fd5b5f826001600160a01b0316634ff0876a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612638573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061265c91906144cc565b90505f836001600160a01b031663b13442716040518163ffffffff1660e01b8152600401602060405180830381865afa15801561269b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126bf919061432d565b90506001600160a01b038116156127e2575f816001600160a01b031663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561270d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061273191906143c4565b90505f196001600160401b038216016127b557816001600160a01b031663e054e08b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612780573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127a491906144cc565b6127ae9084614388565b92506127e0565b60016001600160401b03821611156127e05760405163539cea7160e11b815260040160405180910390fd5b505b5f805160206146b18339815191525465ffffffffffff168265ffffffffffff1610156108035760405163121f507960e11b815260040160405180910390fd5b610abc838383613541565b5f610e8d426135f4565b5f80858154811061284957612849614374565b905f5260205f20906003020190505f6128bc7f9d6222a9cceb0fe2dde310f8edcb19b0830b29f25b1550c13fb346905164f82287876040516020016128a1939291909283526020830191909152604082015260600190565b60405160208183030381529060405280519060200120611cea565b6002830154604080516020601f880181900481028201810190925286815292935061290e926001600160a01b0390921691849188908890819084018382808284375f92019190915250611d1692505050565b610a7a57604051638baa579f60e01b815260040160405180910390fd5b5f805f848154811061293f5761293f614374565b5f9182526020822060016003909202010154915061295e6002856145ca565b9050818103612972576001925050506106d9565b818110156129e1575f6129858284614487565b90505f600261299587600161449a565b61299f91906145ca565b90505f8482116129b8576129b38286614487565b6129c2565b6129c28583614487565b90508083116129d9576001955050505050506106d9565b505050612a44565b5f6129ec8383614487565b90505f60026129fc600188614487565b612a0691906145ca565b90505f848211612a1f57612a1a8286614487565b612a29565b612a298583614487565b9050808311612a40576001955050505050506106d9565b5050505b505f949350505050565b5f612a59878761362a565b80519091508483141580612a6d5750848114155b15612a8b576040516351c4859160e01b815260040160405180910390fd5b5f612adc5f612ab87f779150488f5e984d1f840ba606e388ada6c73b44f261274c3595c61a30023e005490565b6001600160601b031960609190911b166bffffffffffffffffffffffff9091161790565b90505f5b82811015612c7b575f848281518110612afb57612afb614374565b602002602001015190505f816001600160a01b031663ce9b79306040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b66919061432d565b6001600160a01b031663e02f6937858d8f8e8e89818110612b8957612b89614374565b9050602002810190612b9b91906145d8565b6040518663ffffffff1660e01b8152600401612bbb95949392919061461a565b602060405180830381865afa158015612bd6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bfa9190614438565b9050805f03612c0a575050612c73565b612c6f8c83868e858d8d8a818110612c2457612c24614374565b9050602002810190612c3691906145d8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506113f792505050565b5050505b600101612ae0565b50505050505050505050565b6001600160a01b0381165f9081527f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db05602052604081205f805160206146f1833981519152906112ad90613100565b5f816001600160a01b031663ce9b79306040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d12573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d36919061432d565b905060026001600160401b0316816001600160a01b031663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d7f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da391906143c4565b6001600160401b0316141580612e2a5750826001600160a01b0316816001600160a01b031663570ca7356040518163ffffffff1660e01b8152600401602060405180830381865afa158015612dfa573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e1e919061432d565b6001600160a01b031614155b15610abc57604051634e4f76bb60e11b815260040160405180910390fd5b5f6112aa846001600160a01b038086169085166137a7565b6001600160a01b0381165f9081526001850160205260408120549003612e995760405163aba4733960e01b815260040160405180910390fd5b6001600160a01b0381165f908152600180860160205260409091205461080391859185918891612ec99190614487565b81548110612ed957612ed9614374565b905f5260205f2090600202016001016137c39092919063ffffffff16565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115612f3057505f91506003905082612fb5565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015612f81573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116612fac57505f925060019150829050612fb5565b92505f91508190505b9450945094915050565b81545f9065ffffffffffff80841691161080156106d657508254600160301b900465ffffffffffff1615806106d6575050905465ffffffffffff918216600160301b909104909116101590565b5f610e8d61384e565b5f805f856001600160a01b0316858560405160240161303592919061466f565b60408051601f198184030181529181526020820180516001600160e01b0316630b135d3f60e11b1790525161306a9190613c4d565b5f60405180830381855afa9150503d805f81146130a2576040519150601f19603f3d011682016040523d82523d5f602084013e6130a7565b606091505b50915091508180156130bb57506020815110155b80156130e257508051630b135d3f60e11b906130e09083016020908101908401614438565b145b9695505050505050565b5f6106d6836001600160a01b0384166138c1565b5f6106d9825490565b6001600160a01b0381165f908152600185016020526040812054808203613133575f9150506118e3565b6130e2858588613144600186614487565b8154811061315457613154614374565b905f5260205f2090600202016001016138dd9092919063ffffffff16565b5f805f805160206147118339815191525b546001600160a01b031692915050565b6001600160a01b0381165f908152600185016020526040812054908190036131ce5760405163aba4733960e01b815260040160405180910390fd5b806131d881614687565b9150506132128484875f0184815481106131f4576131f4614374565b905f5260205f20906002020160010161393e9092919063ffffffff16565b61321d81600161449a565b855411613289576001600160a01b0382165f908152600186016020526040812055845485908061324f5761324f61469c565b5f8281526020902060025f199092019182020180546001600160a01b031916815560010180546001600160601b0319169055905550610803565b8454859061329990600190614487565b815481106132a9576132a9614374565b905f5260205f209060020201855f0182815481106132c9576132c9614374565b5f9182526020909120825460029092020180546001600160a01b0319166001600160a01b039092169190911781556001918201805492909101805465ffffffffffff19811665ffffffffffff94851690811783559254600160301b908190049094169093026001600160601b031990931690911791909117905584548590806133545761335461469c565b5f828152602080822060025f199094019384020180546001600160a01b0319168155600190810180546001600160601b0319169055929093556001600160a01b038516815287820190925260408220919091556133b290829061449a565b856001015f875f0184815481106133cb576133cb614374565b5f91825260208083206002909202909101546001600160a01b031683528201929092526040019020555050505050565b5f5f805160206146f18339815191526118e37f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db03858561129e565b6001600160a01b0382165f9081527f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db05602052604081205f805160206146f18339815191529061073b90868561129e565b6001600160a01b0381165f90815260018401602052604081205490036134be5760405163aba4733960e01b815260040160405180910390fd5b6001600160a01b0381165f9081526001808501602052604090912054610abc91849186916134eb91614487565b815481106134fb576134fb614374565b905f5260205f2090600202016001016139c890919063ffffffff16565b5f805f805160206146f1833981519152613183565b5f6106d6836001600160a01b038416613a1b565b6001600160a01b0381165f9081526001840160205260409020541561357957604051630ea075bf60e21b815260040160405180910390fd5b8254600180820185555f85815260209020600290920290910180546001600160a01b0319166001600160a01b038416178155906135ce9082018481546001600160601b03191665ffffffffffff909116179055565b5082546001600160a01b039091165f908152600190930160205260409092209190915550565b5f65ffffffffffff821115613626576040516306dfcc6560e41b81526030600482015260248101839052604401610dd3565b5090565b60605f805160206146f18339815191525f6136657f485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db03866118d6565b6001600160a01b0385165f90815260058401602052604081209192509061368c90876118d6565b82518151919250905f61369f828461449a565b6001600160401b038111156136b6576136b6613c92565b6040519080825280602002602001820160405280156136df578160200160208202803683370190505b5090505f5b83811015613738578581815181106136fe576136fe614374565b602002602001015182828151811061371857613718614374565b6001600160a01b03909216602092830291909101909101526001016136e4565b505f5b8281101561379a5784818151811061375557613755614374565b602002602001015182828661376a919061449a565b8151811061377a5761377a614374565b6001600160a01b039092166020928302919091019091015260010161373b565b5098975050505050505050565b5f82815260028401602052604081208290556112aa8484613a26565b825465ffffffffffff16156137eb57604051637952fbad60e11b815260040160405180910390fd5b825465ffffffffffff8084169161380b918491600160301b9004166143a6565b65ffffffffffff16111561383257604051631ba9803b60e11b815260040160405180910390fd5b5081546001600160601b03191665ffffffffffff909116179055565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f613878613a31565b613880613a99565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f81815260028301602052604081208190556106d68383613adb565b82545f9065ffffffffffff1615801561390557508354600160301b900465ffffffffffff1615155b80156112aa5750835465ffffffffffff8085169161392c918591600160301b9004166143a6565b65ffffffffffff161115949350505050565b825465ffffffffffff1615158061396357508254600160301b900465ffffffffffff16155b156139815760405163c0f9610560e01b815260040160405180910390fd5b825465ffffffffffff808416916139a1918491600160301b9004166143a6565b65ffffffffffff161115610abc57604051631ba9803b60e11b815260040160405180910390fd5b8154600160301b900465ffffffffffff16156139f757604051633f54562b60e11b815260040160405180910390fd5b815465ffffffffffff91909116600160301b026001600160601b0319909116179055565b5f6106d68383613ae6565b5f6106d68383613afd565b5f5f8051602061473183398151915281613a496117ab565b805190915015613a6157805160209091012092915050565b81548015613a70579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b5f5f8051602061473183398151915281613ab161186b565b805190915015613ac957805160209091012092915050565b60018201548015613a70579392505050565b5f6106d68383613b49565b5f81815260018301602052604081205415156106d6565b5f818152600183016020526040812054613b4257508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106d9565b505f6106d9565b5f8181526001830160205260408120548015613c23575f613b6b600183614487565b85549091505f90613b7e90600190614487565b9050808214613bdd575f865f018281548110613b9c57613b9c614374565b905f5260205f200154905080875f018481548110613bbc57613bbc614374565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613bee57613bee61469c565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506106d9565b5f9150506106d9565b8284823760609190911b6001600160601b0319169101908152601401919050565b5f82518060208501845e5f920191825250919050565b6001600160a01b03811681146106a6575f80fd5b5f60208284031215613c87575f80fd5b81356112ad81613c63565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112613cb5575f80fd5b81356001600160401b03811115613cce57613cce613c92565b604051601f8201601f19908116603f011681016001600160401b0381118282101715613cfc57613cfc613c92565b604052818152838201602001851015613d13575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613d40575f80fd5b8235915060208301356001600160401b03811115613d5c575f80fd5b613d6885828601613ca6565b9150509250929050565b65ffffffffffff811681146106a6575f80fd5b5f8060408385031215613d96575f80fd5b8235613da181613d72565b915060208301356001600160401b03811115613d5c575f80fd5b5f805f60608486031215613dcd575f80fd5b8335613dd881613c63565b92506020840135613de881613c63565b915060408401356001600160401b03811115613e02575f80fd5b613e0e86828701613ca6565b9150509250925092565b5f805f8060808587031215613e2b575f80fd5b8435613e3681613c63565b935060208501356001600160401b03811115613e50575f80fd5b613e5c87828801613ca6565b93505060408501356001600160401b03811115613e77575f80fd5b613e8387828801613ca6565b92505060608501356001600160401b03811115613e9e575f80fd5b613eaa87828801613ca6565b91505092959194509250565b5f60208284031215613ec6575f80fd5b81356001600160401b03811115613edb575f80fd5b6118e384828501613ca6565b5f805f805f60a08688031215613efb575f80fd5b8535613f0681613c63565b945060208601356001600160401b03811115613f20575f80fd5b613f2c88828901613ca6565b9450506040860135613f3d81613c63565b925060608601356001600160401b03811115613f57575f80fd5b613f6388828901613ca6565b92505060808601356001600160401b03811115613f7e575f80fd5b613f8a88828901613ca6565b9150509295509295909350565b5f805f60608486031215613fa9575f80fd5b83356001600160401b03811115613fbe575f80fd5b613fca86828701613ca6565b9350506020840135613de881613c63565b5f8060408385031215613fec575f80fd5b8235613da181613c63565b5f805f805f8060c0878903121561400c575f80fd5b863561401781613d72565b9550602087013561402781613c63565b945060408701359350606087013561403e81613c63565b92506080870135915060a08701356001600160401b0381111561405f575f80fd5b61406b89828a01613ca6565b9150509295509295509295565b5f8060408385031215614089575f80fd5b82359150602083013561409b81613c63565b809150509250929050565b5f80604083850312156140b7575f80fd5b82356140c281613c63565b946020939093013593505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60ff60f81b8816815260e060208201525f61411c60e08301896140d0565b828103604084015261412e81896140d0565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b81811015614183578351835260209384019390920191600101614165565b50909b9a5050505050505050505050565b5f602082840312156141a4575f80fd5b5035919050565b602081525f6106d660208301846140d0565b5f80604083850312156141ce575f80fd5b82356001600160401b038111156141e3575f80fd5b6141ef85828601613ca6565b92505060208301356001600160401b03811115613d5c575f80fd5b5f8083601f84011261421a575f80fd5b5081356001600160401b03811115614230575f80fd5b6020830191508360208260051b850101111561424a575f80fd5b9250929050565b5f805f805f805f8060a0898b031215614268575f80fd5b883597506020890135965060408901356001600160401b0381111561428b575f80fd5b8901601f81018b1361429b575f80fd5b80356001600160401b038111156142b0575f80fd5b8b60208284010111156142c1575f80fd5b6020919091019650945060608901356001600160401b038111156142e3575f80fd5b6142ef8b828c0161420a565b90955093505060808901356001600160401b0381111561430d575f80fd5b6143198b828c0161420a565b999c989b5096995094979396929594505050565b5f6020828403121561433d575f80fd5b81516112ad81613c63565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161436d5761436d614348565b5060010190565b634e487b7160e01b5f52603260045260245ffd5b65ffffffffffff82811682821603908111156106d9576106d9614348565b65ffffffffffff81811683821601908111156106d9576106d9614348565b5f602082840312156143d4575f80fd5b81516001600160401b03811681146112ad575f80fd5b634e487b7160e01b5f52602160045260245ffd5b85815260018060a01b038516602082015283604082015265ffffffffffff8316606082015260a060808201525f611e9d60a08301846140d0565b5f60208284031215614448575f80fd5b5051919050565b600181811c9082168061446357607f821691505b60208210810361448157634e487b7160e01b5f52602260045260245ffd5b50919050565b818103818111156106d9576106d9614348565b808201808211156106d9576106d9614348565b5f602082840312156144bd575f80fd5b815180151581146112ad575f80fd5b5f602082840312156144dc575f80fd5b81516112ad81613d72565b6001815b60018411156145225780850481111561450657614506614348565b600184161561451457908102905b60019390931c9280026144eb565b935093915050565b5f82614538575060016106d9565b8161454457505f6106d9565b816001811461455a576002811461456457614580565b60019150506106d9565b60ff84111561457557614575614348565b50506001821b6106d9565b5060208310610133831016604e8410600b84101617156145a3575081810a6106d9565b6145af5f1984846144e7565b805f19048211156145c2576145c2614348565b029392505050565b5f6106d660ff84168361452a565b5f808335601e198436030181126145ed575f80fd5b8301803591506001600160401b03821115614606575f80fd5b60200191503681900382131561424a575f80fd5b8581526001600160a01b038516602082015265ffffffffffff841660408201526080606082018190528101829052818360a08301375f81830160a090810191909152601f909201601f19160101949350505050565b828152604060208201525f6112aa60408301846140d0565b5f8161469557614695614348565b505f190190565b634e487b7160e01b5f52603160045260245ffdfe52becd5b30d67421b1f63b9d90d513daf82b3973912d3edfdac9468c1743c0007c1bcd600c3fcfbc53470fac03a90d5cf6aa7b77c3f1ed10e6c6bd4d192eaf00485f0695561726d087d0cb5cf546efed37ef61dfced21455f1ba7eb5e5b3db003b2b549db680c436ebf9aa3c8eeee850852f16da5cdb5137dbc0299ebb219e00a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d1003da47716e6090d5a5545e03387f4dac112d37cd069a5573bb81de8579bd9dc00a2646970667358221220efba82b0262fa824f848cbf709f95c96f9891078d81449b0f6c97c04b0e9396a64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007d03b7343bf8d5cec7c0c27ece084a20113d15c900000000000000000000000000000000000000000000000000000000000151800000000000000000000000006f75a4fff97326a00e52662d82ea4fde86a2c548000000000000000000000000407a039d94948484d356efb765b3c74382a050b400000000000000000000000058973d16ffa900d11fc22e5e2b6840d9f7e1340100000000000000000000000094fe567e412fc828aa3403403c7b980de2713b2100000000000000000000000068e7df0a38467cb511c6ce43bded70f202a0b8f6
-----Decoded View---------------
Arg [0] : networkRegistry (address): 0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9
Arg [1] : slashingWindow (uint48): 86400
Arg [2] : operatorRegistry (address): 0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548
Arg [3] : vaultRegistry (address): 0x407A039D94948484D356eFB765b3c74382A050B4
Arg [4] : operatorNetOptin (address): 0x58973d16FFA900D11fC22e5e2B6840d9f7e13401
Arg [5] : reader (address): 0x94fe567e412Fc828AA3403403C7b980De2713B21
Arg [6] : owner (address): 0x68e7Df0a38467Cb511C6cE43BDED70F202A0B8F6
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000007d03b7343bf8d5cec7c0c27ece084a20113d15c9
Arg [1] : 0000000000000000000000000000000000000000000000000000000000015180
Arg [2] : 0000000000000000000000006f75a4fff97326a00e52662d82ea4fde86a2c548
Arg [3] : 000000000000000000000000407a039d94948484d356efb765b3c74382a050b4
Arg [4] : 00000000000000000000000058973d16ffa900d11fc22e5e2b6840d9f7e13401
Arg [5] : 00000000000000000000000094fe567e412fc828aa3403403c7b980de2713b21
Arg [6] : 00000000000000000000000068e7df0a38467cb511c6ce43bded70f202a0b8f6
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.