Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 12 from a total of 12 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Submit Task | 2398702 | 70 days ago | IN | 0 ETH | 0.00003762 | ||||
Create Task | 2398701 | 70 days ago | IN | 0 ETH | 0.00004732 | ||||
Submit Task | 2398522 | 70 days ago | IN | 0 ETH | 0.00003999 | ||||
Create Task | 2398521 | 70 days ago | IN | 0 ETH | 0.00005029 | ||||
Create Task | 2398520 | 70 days ago | IN | 0 ETH | 0.00005029 | ||||
Submit Task | 2398514 | 70 days ago | IN | 0 ETH | 0.00003999 | ||||
Create Task | 2398500 | 70 days ago | IN | 0 ETH | 0.0000622 | ||||
Create Task | 2398498 | 70 days ago | IN | 0 ETH | 0.0000622 | ||||
Register Vault | 2397412 | 70 days ago | IN | 0 ETH | 0.00002197 | ||||
Register Operato... | 2397408 | 70 days ago | IN | 0 ETH | 0.00003841 | ||||
Register Operato... | 2397407 | 70 days ago | IN | 0 ETH | 0.00003841 | ||||
Register Operato... | 2397406 | 70 days ago | IN | 0 ETH | 0.00004357 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
CatalysisMiddleware
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IRegistry} from "@symbiotic/interfaces/common/IRegistry.sol"; import {IOptInService} from "@symbiotic/interfaces/service/IOptInService.sol"; import {IVault} from "@symbiotic/interfaces/vault/IVault.sol"; import {IBaseDelegator} from "@symbiotic/interfaces/delegator/IBaseDelegator.sol"; import {IVetoSlasher} from "@symbiotic/interfaces/slasher/IVetoSlasher.sol"; import {IEntity} from "@symbiotic/interfaces/common/IEntity.sol"; import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {MapWithTimeData} from "./libraries/MapWithTimeData.sol"; import {Subnetwork} from "@symbiotic/contracts/libraries/Subnetwork.sol"; contract CatalysisMiddleware is Ownable { using EnumerableMap for EnumerableMap.AddressToUintMap; using MapWithTimeData for EnumerableMap.AddressToUintMap; using ECDSA for bytes32; using MessageHashUtils for bytes32; using Subnetwork for address; error OperatorAlreadyRegistered(); error OperatorNotRegistered(); error InvalidOperatorAddress(); error OperatorNotOptedIn(); error OperatorNotRegisteredInRegistry(); error VaultAlreadyRegistered(); error NotVault(); error VaultEpochTooShort(); error AlreadyAdded(); error SlashingWindowTooShort(); error TooOldEpoch(); error InvalidEpoch(); error OperarorGracePeriodNotPassed(); error VaultGracePeriodNotPassed(); error InvalidSubnetworksCnt(); enum OperatorAVSRegistrationStatus { UNREGISTERED, // Operator not registered to AVS REGISTERED // Operator registered to AVS } address public immutable NETWORK; address public immutable OPERATOR_REGISTRY; address public immutable VAULT_REGISTRY; address public immutable OPERATOR_NET_OPTIN; uint48 public immutable SLASHING_WINDOW; uint48 public immutable EPOCH_DURATION; uint48 public immutable START_TIME; uint48 private constant INSTANT_SLASHER_TYPE = 0; uint48 private constant VETO_SLASHER_TYPE = 1; struct Task { string message; uint256 blockNumber; uint256 operatorIndex; bool completed; } Task[] public tasks; event TaskCreated(uint256 indexed taskId, string message, uint256 blockNumber, uint256 operatorIndex); event TaskSubmitted(uint256 indexed taskId, address operator); event OperatorRegistered(address indexed operatorAddress, uint256 operatorIndex); event OperatorUnregistered(address indexed operatorAddress); event VaultRegistered(address indexed vaultAddress); EnumerableMap.AddressToUintMap private vaults; constructor( address _network, address _operatorRegistry, address _vaultRegistry, address _operatorNetOptin, uint48 _epochDuration, uint48 _slashingWindow ) Ownable(msg.sender) { if (_slashingWindow < _epochDuration) { revert SlashingWindowTooShort(); } NETWORK = _network; OPERATOR_REGISTRY = _operatorRegistry; VAULT_REGISTRY = _vaultRegistry; OPERATOR_NET_OPTIN = _operatorNetOptin; EPOCH_DURATION = _epochDuration; SLASHING_WINDOW = _slashingWindow; START_TIME = Time.timestamp(); subnetworksCnt = 1; } // Operator set consists of a list of operator data and a mapping from operator address to index in the list. address[] public operatorSet; EnumerableMap.AddressToUintMap private operatorAddressToIndex; EnumerableMap.AddressToUintMap private operatorAddressWithTime; mapping(address => OperatorAVSRegistrationStatus) private operatorStatus; mapping(uint48 => uint256) public totalStakeCache; mapping(uint48 => bool) public totalStakeCached; mapping(uint48 => mapping(address => uint256)) public operatorStakeCache; uint256 public subnetworksCnt; modifier onlyOperator() { require(operatorAddressToIndex.contains(msg.sender), "Caller is not a registered operator"); _; } /** * @dev Returns the timestamp of the start of a given epoch. * @param epoch The epoch number. * @return timestamp The timestamp of the start of the epoch. */ function getEpochStartTs(uint48 epoch) public view returns (uint48 timestamp) { return START_TIME + epoch * EPOCH_DURATION; } /** * @dev Returns the epoch number for a given timestamp. * @param timestamp The timestamp to check. * @return epoch The epoch number corresponding to the timestamp. */ function getEpochAtTs(uint48 timestamp) public view returns (uint48 epoch) { return (timestamp - START_TIME) / EPOCH_DURATION; } /** * @dev Returns the current epoch number. * @return epoch The current epoch number. */ function getCurrentEpoch() public view returns (uint48 epoch) { return getEpochAtTs(Time.timestamp()); } /** * @dev Registers a new operator. * @param _operatorAddress Address of the operator. */ function registerOperator( address _operatorAddress ) external onlyOwner { if (operatorAddressToIndex.contains(_operatorAddress)) { revert OperatorAlreadyRegistered(); } if (_operatorAddress == address(0)) { revert InvalidOperatorAddress(); } if (!IRegistry(OPERATOR_REGISTRY).isEntity(_operatorAddress)) { revert OperatorNotRegisteredInRegistry(); } // Check if the operator is opted in to the OPERATOR_NET_OPTIN. if (!IOptInService(OPERATOR_NET_OPTIN).isOptedIn(_operatorAddress, NETWORK)) { revert OperatorNotOptedIn(); } operatorSet.push(_operatorAddress); operatorAddressToIndex.set(_operatorAddress, operatorSet.length - 1); operatorAddressWithTime.add(_operatorAddress); operatorAddressWithTime.enable(_operatorAddress); operatorStatus[_operatorAddress] = OperatorAVSRegistrationStatus.REGISTERED; emit OperatorRegistered(_operatorAddress, operatorSet.length - 1); } /** * @dev Updates the status of an existing operator to unregistered. * @param _operatorAddress Address of the operator to unregister. */ function unregisterOperator(address _operatorAddress) external onlyOwner { require(_operatorAddress != address(0), "Invalid operator address"); uint256 index = operatorAddressToIndex.get(_operatorAddress); require(index != 0, "Operator not registered"); // Update the operator's status to unregistered operatorStatus[_operatorAddress] = OperatorAVSRegistrationStatus.UNREGISTERED; (, uint48 disabledTime) = operatorAddressWithTime.getTimes(_operatorAddress); if (disabledTime == 0 || disabledTime + SLASHING_WINDOW > Time.timestamp()) { revert OperarorGracePeriodNotPassed(); } operatorAddressWithTime.remove(_operatorAddress); emit OperatorUnregistered(_operatorAddress); } /** * @dev Returns the index of the given operator address in the operator set. * @param _operatorAddress The address of the operator to look up. * @return The index of the operator in the set, or 0 if the operator is not registered. */ function getOperatorIndex(address _operatorAddress) external view returns (uint256) { return operatorAddressToIndex.get(_operatorAddress); } /** * @dev Returns the operator set. * @return The array of operator addresses. */ function getOperatorSet() external view returns (address[] memory) { return operatorSet; } /** * @dev Pauses an operator. * @param operator The address of the operator to pause. */ function pauseOperator(address operator) external onlyOwner { operatorAddressWithTime.disable(operator); } /** * @dev Unpauses an operator. * @param operator The address of the operator to unpause. */ function unpauseOperator(address operator) external onlyOwner { operatorAddressWithTime.enable(operator); } /** * @dev Registers a new vault for the AVS. * @param _vaultAddress Address of the vault to register. */ function registerVault(address _vaultAddress) external onlyOwner { if (vaults.contains(_vaultAddress)) { revert VaultAlreadyRegistered(); } if (!IRegistry(VAULT_REGISTRY).isEntity(_vaultAddress)) { revert NotVault(); } uint48 vaultEpoch = IVault(_vaultAddress).epochDuration(); address slasher = IVault(_vaultAddress).slasher(); if (slasher != address(0) && IEntity(slasher).TYPE() == VETO_SLASHER_TYPE) { vaultEpoch -= IVetoSlasher(slasher).vetoDuration(); } if (vaultEpoch < SLASHING_WINDOW) { revert VaultEpochTooShort(); } vaults.add(_vaultAddress); vaults.enable(_vaultAddress); emit VaultRegistered(_vaultAddress); } /** * @dev Checks if a vault is registered. * @param _vaultAddress Address of the vault to check. * @return bool True if the vault is registered, false otherwise. */ function isVaultRegistered(address _vaultAddress) public view returns (bool) { return vaults.contains(_vaultAddress); } /** * @dev Returns the list of registered vaults. * @return address[] Array of registered vault addresses. */ function getRegisteredVaults() external view returns (address[] memory) { return vaults.keys(); } /** * @dev Pauses a vault. * @param vault The address of the vault to pause. */ function pauseVault(address vault) external onlyOwner { vaults.disable(vault); } /** * @dev Unpauses a vault. * @param vault The address of the vault to unpause. */ function unpauseVault(address vault) external onlyOwner { vaults.enable(vault); } /** * @dev Sets the number of subnetworks. * @param _subnetworksCnt The number of subnetworks. */ function setSubnetworksCnt(uint256 _subnetworksCnt) external onlyOwner { if (subnetworksCnt >= _subnetworksCnt) { revert InvalidSubnetworksCnt(); } subnetworksCnt = _subnetworksCnt; } /** * @dev Unregisters a vault. * @param vault The address of the vault to unregister. */ function unregisterVault(address vault) external onlyOwner { (, uint48 disabledTime) = vaults.getTimes(vault); if (disabledTime == 0 || disabledTime + SLASHING_WINDOW > Time.timestamp()) { revert VaultGracePeriodNotPassed(); } vaults.remove(vault); } /** * @dev Gets the stake of an operator for a specific epoch. * @param operator The address of the operator. * @param epoch The epoch number. * @return stake The stake of the operator. */ function getOperatorStake(address operator, uint48 epoch) public view returns (uint256 stake) { if (totalStakeCached[epoch]) { return operatorStakeCache[epoch][operator]; } uint48 epochStartTs = getEpochStartTs(epoch); for (uint256 i; i < vaults.length(); ++i) { (address vault, uint48 enabledTime, uint48 disabledTime) = vaults.atWithTimes(i); // just skip the vault if it was enabled after the target epoch or not enabled if (!_wasActiveAt(enabledTime, disabledTime, epochStartTs)) { continue; } for (uint96 j = 0; j < subnetworksCnt; ++j) { stake += IBaseDelegator(IVault(vault).delegator()).stakeAt( NETWORK.subnetwork(j), operator, epochStartTs, new bytes(0) ); } } return stake; } /** * @dev Gets the total stake for a specific epoch. * @param epoch The epoch number. * @return The total stake for the epoch. */ function getTotalStake(uint48 epoch) public view returns (uint256) { if (totalStakeCached[epoch]) { return totalStakeCache[epoch]; } return _calcTotalStake(epoch); } /** * @dev Calculates and caches the stakes for a specific epoch. * @param epoch The epoch number. * @return totalStake The total stake for the epoch. */ function calcAndCacheStakes(uint48 epoch) public returns (uint256 totalStake) { uint48 epochStartTs = getEpochStartTs(epoch); // for epoch older than SLASHING_WINDOW total stake can be invalidated (use cache) if (epochStartTs < Time.timestamp() - SLASHING_WINDOW) { revert TooOldEpoch(); } if (epochStartTs > Time.timestamp()) { revert InvalidEpoch(); } for (uint256 i; i < operatorAddressWithTime.length(); ++i) { (address operator, uint48 enabledTime, uint48 disabledTime) = operatorAddressWithTime.atWithTimes(i); // just skip operator if it was added after the target epoch or paused if (!_wasActiveAt(enabledTime, disabledTime, epochStartTs)) { continue; } uint256 operatorStake = getOperatorStake(operator, epochStartTs); operatorStakeCache[epoch][operator] = operatorStake; totalStake += operatorStake; } totalStakeCached[epoch] = true; totalStakeCache[epoch] = totalStake; } /** * @dev Calculates the total stake for a specific epoch. * @param epoch The epoch number. * @return totalStake The total stake for the epoch. */ function _calcTotalStake(uint48 epoch) private view returns (uint256 totalStake) { uint48 epochStartTs = getEpochStartTs(epoch); // for epoch older than SLASHING_WINDOW total stake can be invalidated (use cache) if (epochStartTs < Time.timestamp() - SLASHING_WINDOW) { revert TooOldEpoch(); } if (epochStartTs > Time.timestamp()) { revert InvalidEpoch(); } for (uint256 i; i < operatorAddressWithTime.length(); ++i) { (address operator, uint48 enabledTime, uint48 disabledTime) = operatorAddressWithTime.atWithTimes(i); // just skip operator if it was added after the target epoch or paused if (!_wasActiveAt(enabledTime, disabledTime, epochStartTs)) { continue; } uint256 operatorStake = getOperatorStake(operator, epochStartTs); totalStake += operatorStake; } } /** * @dev Checks if an entity was active at a specific timestamp. * @param enabledTime The time the entity was enabled. * @param disabledTime The time the entity was disabled. * @param timestamp The timestamp to check. * @return bool True if the entity was active at the timestamp, false otherwise. */ function _wasActiveAt(uint48 enabledTime, uint48 disabledTime, uint48 timestamp) private pure returns (bool) { return enabledTime != 0 && enabledTime <= timestamp && (disabledTime == 0 || disabledTime >= timestamp); } /** * @dev Creates a new task and assigns an operator based on the block number. * @param _message The message for the task. * @return taskId The ID of the newly created task. */ function createTask(string memory _message) external returns (uint256 taskId) { require(bytes(_message).length > 0, "Message cannot be empty"); require(operatorSet.length > 0, "No operators registered"); uint256 blockNumber = block.number; uint256 operatorIndex = blockNumber % operatorSet.length; Task memory newTask = Task({ message: _message, blockNumber: blockNumber, operatorIndex: operatorIndex, completed: false }); tasks.push(newTask); taskId = tasks.length - 1; emit TaskCreated(taskId, _message, blockNumber, operatorIndex); } /** * @dev Submits a task with a payload and signature. Can only be called by a registered operator. * @param _taskId The ID of the task to submit. * @param _signature The signature of the payload. */ function submitTask(uint256 _taskId, bytes calldata _signature) external onlyOperator { require(_taskId < tasks.length, "Invalid task ID"); Task storage task = tasks[_taskId]; uint256 operatorIndex = operatorAddressToIndex.get(msg.sender); require(task.operatorIndex == operatorIndex, "Task not assigned to this operator"); // Reconstruct the message that was signed bytes32 messageHash = keccak256(abi.encodePacked(task.message, _taskId, task.blockNumber)); bytes32 ethSignedMessageHash = messageHash.toEthSignedMessageHash(); // Recover the signer's address address signer = ethSignedMessageHash.recover(_signature); // Verify that the recovered signer matches the operator's address require(signer == msg.sender, "Invalid signature"); // Mark the task as completed tasks[_taskId].completed = true; emit TaskSubmitted(_taskId, msg.sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.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, uint32, uint48) { (uint32 valueBefore, uint32 valueAfter, uint48 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, uint32, uint48) { 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 // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// 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 IOptInService { error AlreadyOptedIn(); error NotOptedIn(); error NotWhereEntity(); error NotWho(); error OptOutCooldown(); /** * @notice Emitted when a "who" opts into a "where" entity. * @param who address of the "who" * @param where address of the "where" entity */ event OptIn(address indexed who, address indexed where); /** * @notice Emitted when a "who" opts out from a "where" entity. * @param who address of the "who" * @param where address of the "where" entity */ event OptOut(address indexed who, address indexed where); /** * @notice Get the "who" registry's address. * @return address of the "who" registry */ function WHO_REGISTRY() external view returns (address); /** * @notice Get the address of the registry where to opt-in. * @return address of the "where" registry */ function WHERE_REGISTRY() external view returns (address); /** * @notice Get if a given "who" is opted-in to a particular "where" entity at a given timestamp using a hint. * @param who address of the "who" * @param where address of the "where" registry * @param timestamp time point to get if the "who" is opted-in at * @param hint hint for the checkpoint index * @return if the "who" is opted-in at the given timestamp */ function isOptedInAt( address who, address where, uint48 timestamp, bytes calldata hint ) external view returns (bool); /** * @notice Check if a given "who" is opted-in to a particular "where" entity. * @param who address of the "who" * @param where address of the "where" registry * @return if the "who" is opted-in */ function isOptedIn(address who, address where) external view returns (bool); /** * @notice Opt-in a calling "who" to a particular "where" entity. * @param where address of the "where" registry */ function optIn( address where ) external; /** * @notice Opt-out a calling "who" from a particular "where" entity. * @param where address of the "where" registry */ function optOut( address where ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IMigratableEntity} from "../common/IMigratableEntity.sol"; import {IVaultStorage} from "./IVaultStorage.sol"; interface IVault is IMigratableEntity, IVaultStorage { error AlreadyClaimed(); error AlreadySet(); error DepositLimitReached(); error InsufficientClaim(); error InsufficientDeposit(); error InsufficientRedemption(); error InsufficientWithdrawal(); error InvalidAccount(); error InvalidCaptureEpoch(); error InvalidClaimer(); error InvalidCollateral(); error InvalidEpoch(); error InvalidEpochDuration(); error InvalidLengthEpochs(); error InvalidOnBehalfOf(); error InvalidRecipient(); error MissingRoles(); error NoDepositLimit(); error NoDepositWhitelist(); error NotDelegator(); error NotSlasher(); error NotWhitelistedDepositor(); error TooMuchRedeem(); error TooMuchWithdraw(); /** * @notice Initial parameters needed for a vault deployment. * @param collateral vault's underlying collateral * @param delegator vault's delegator to delegate the stake to networks and operators * @param slasher vault's slasher to provide a slashing mechanism to networks * @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 delegator; address slasher; address burner; uint48 epochDuration; bool depositWhitelist; bool isDepositLimit; uint256 depositLimit; address defaultAdminRoleHolder; address depositWhitelistSetRoleHolder; address depositorWhitelistRoleHolder; address isDepositLimitSetRoleHolder; address depositLimitSetRoleHolder; } /** * @notice Hints for an active balance. * @param activeSharesOfHint hint for the active shares of checkpoint * @param activeStakeHint hint for the active stake checkpoint * @param activeSharesHint hint for the active shares checkpoint */ struct ActiveBalanceOfHints { bytes activeSharesOfHint; bytes activeStakeHint; bytes activeSharesHint; } /** * @notice Emitted when a deposit is made. * @param depositor account that made the deposit * @param onBehalfOf account the deposit was made on behalf of * @param amount amount of the collateral deposited * @param shares amount of the active shares minted */ event Deposit(address indexed depositor, address indexed onBehalfOf, uint256 amount, uint256 shares); /** * @notice Emitted when a withdrawal is made. * @param withdrawer account that made the withdrawal * @param claimer account that needs to claim the withdrawal * @param amount amount of the collateral withdrawn * @param burnedShares amount of the active shares burned * @param mintedShares amount of the epoch withdrawal shares minted */ event Withdraw( address indexed withdrawer, address indexed claimer, uint256 amount, uint256 burnedShares, uint256 mintedShares ); /** * @notice Emitted when a redemption is made. * @param redeemer account that redeemed * @param claimer account that needs to claim the withdrawal * @param shares amount of the active shares burned * @param withdrawnAssets amount of the collateral withdrawn * @param mintedShares amount of the epoch withdrawal shares minted */ event Redeem( address indexed redeemer, address indexed claimer, uint256 shares, uint256 withdrawnAssets, uint256 mintedShares ); /** * @notice Emitted when a claim is made. * @param claimer account that claimed * @param recipient account that received the collateral * @param epoch epoch the collateral was claimed for * @param amount amount of the collateral claimed */ event Claim(address indexed claimer, address indexed recipient, uint256 epoch, uint256 amount); /** * @notice Emitted when a batch claim is made. * @param claimer account that claimed * @param recipient account that received the collateral * @param epochs epochs the collateral was claimed for * @param amount amount of the collateral claimed */ event ClaimBatch(address indexed claimer, address indexed recipient, uint256[] epochs, uint256 amount); /** * @notice Emitted when a slash happened. * @param slasher address of the slasher * @param slashedAmount amount of the collateral slashed */ event OnSlash(address indexed slasher, uint256 slashedAmount); /** * @notice Emitted when a deposit whitelist status is enabled/disabled. * @param status if enabled deposit whitelist */ event SetDepositWhitelist(bool status); /** * @notice Emitted when a depositor whitelist status is set. * @param account account for which the whitelist status is set * @param status if whitelisted the account */ event SetDepositorWhitelistStatus(address indexed account, bool status); /** * @notice Emitted when a deposit limit status is enabled/disabled. * @param status if enabled deposit limit */ event SetIsDepositLimit(bool status); /** * @notice Emitted when a deposit limit is set. * @param limit deposit limit (maximum amount of the collateral that can be in the vault simultaneously) */ event SetDepositLimit(uint256 limit); /** * @notice Get a total amount of the collateral that can be slashed. * @return total amount of the slashable collateral */ function totalStake() external view returns (uint256); /** * @notice Get an active balance for a particular account at a given timestamp using hints. * @param account account to get the active balance for * @param timestamp time point to get the active balance for the account at * @param hints hints for checkpoints' indexes * @return active balance for the account at the timestamp */ function activeBalanceOfAt( address account, uint48 timestamp, bytes calldata hints ) external view returns (uint256); /** * @notice Get an active balance for a particular account. * @param account account to get the active balance for * @return active balance for the account */ function activeBalanceOf( address account ) external view returns (uint256); /** * @notice Get withdrawals for a particular account at a given epoch (zero if claimed). * @param epoch epoch to get the withdrawals for the account at * @param account account to get the withdrawals for * @return withdrawals for the account at the epoch */ function withdrawalsOf(uint256 epoch, address account) external view returns (uint256); /** * @notice Get a total amount of the collateral that can be slashed for a given account. * @return total amount of the slashable collateral */ function slashableBalanceOf( address account ) external view returns (uint256); /** * @notice Deposit collateral into the vault. * @param onBehalfOf account the deposit is made on behalf of * @param amount amount of the collateral to deposit * @return depositedAmount amount of the collateral deposited * @return mintedShares amount of the active shares minted */ function deposit( address onBehalfOf, uint256 amount ) external returns (uint256 depositedAmount, uint256 mintedShares); /** * @notice Withdraw collateral from the vault (it will be claimable after the next epoch). * @param claimer account that needs to claim the withdrawal * @param amount amount of the collateral to withdraw * @return burnedShares amount of the active shares burned * @return mintedShares amount of the epoch withdrawal shares minted */ function withdraw(address claimer, uint256 amount) external returns (uint256 burnedShares, uint256 mintedShares); /** * @notice Redeem collateral from the vault (it will be claimable after the next epoch). * @param claimer account that needs to claim the withdrawal * @param shares amount of the active shares to redeem * @return withdrawnAssets amount of the collateral withdrawn * @return mintedShares amount of the epoch withdrawal shares minted */ function redeem(address claimer, uint256 shares) external returns (uint256 withdrawnAssets, uint256 mintedShares); /** * @notice Claim collateral from the vault. * @param recipient account that receives the collateral * @param epoch epoch to claim the collateral for * @return amount amount of the collateral claimed */ function claim(address recipient, uint256 epoch) external returns (uint256 amount); /** * @notice Claim collateral from the vault for multiple epochs. * @param recipient account that receives the collateral * @param epochs epochs to claim the collateral for * @return amount amount of the collateral claimed */ function claimBatch(address recipient, uint256[] calldata epochs) external returns (uint256 amount); /** * @notice Slash callback for burning collateral. * @param slashedAmount amount to slash * @param captureTimestamp time point when the stake was captured * @dev Only the slasher can call this function. */ function onSlash(uint256 slashedAmount, uint48 captureTimestamp) external; /** * @notice Enable/disable deposit whitelist. * @param status if enabling deposit whitelist * @dev Only a DEPOSIT_WHITELIST_SET_ROLE holder can call this function. */ function setDepositWhitelist( bool status ) external; /** * @notice Set a depositor whitelist status. * @param account account for which the whitelist status is set * @param status if whitelisting the account * @dev Only a DEPOSITOR_WHITELIST_ROLE holder can call this function. */ function setDepositorWhitelistStatus(address account, bool status) external; /** * @notice Enable/disable deposit limit. * @param status if enabling deposit limit * @dev Only a IS_DEPOSIT_LIMIT_SET_ROLE holder can call this function. */ function setIsDepositLimit( bool status ) external; /** * @notice Set a deposit limit. * @param limit deposit limit (maximum amount of the collateral that can be in the vault simultaneously) * @dev Only a DEPOSIT_LIMIT_SET_ROLE holder can call this function. */ function setDepositLimit( uint256 limit ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IEntity} from "../common/IEntity.sol"; interface IBaseDelegator is IEntity { error AlreadySet(); error InsufficientHookGas(); error NotNetwork(); error NotSlasher(); error NotVault(); /** * @notice Base parameters needed for delegators' deployment. * @param defaultAdminRoleHolder address of the initial DEFAULT_ADMIN_ROLE holder * @param hook address of the hook contract * @param hookSetRoleHolder address of the initial HOOK_SET_ROLE holder */ struct BaseParams { address defaultAdminRoleHolder; address hook; address hookSetRoleHolder; } /** * @notice Base hints for a stake. * @param operatorVaultOptInHint hint for the operator-vault opt-in * @param operatorNetworkOptInHint hint for the operator-network opt-in */ struct StakeBaseHints { bytes operatorVaultOptInHint; bytes operatorNetworkOptInHint; } /** * @notice Emitted when a subnetwork's maximum limit is set. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param amount new maximum subnetwork's limit (how much stake the subnetwork is ready to get) */ event SetMaxNetworkLimit(bytes32 indexed subnetwork, uint256 amount); /** * @notice Emitted when a slash happened. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param slashedAmount amount of the collateral slashed */ event OnSlash(bytes32 indexed subnetwork, address indexed operator, uint256 slashedAmount); /** * @notice Emitted when a hook is set. * @param hook address of the hook */ event SetHook(address indexed hook); /** * @notice Get a version of the delegator (different versions mean different interfaces). * @return version of the delegator * @dev Must return 1 for this one. */ function VERSION() external view returns (uint64); /** * @notice Get the network registry's address. * @return address of the network registry */ function NETWORK_REGISTRY() external view returns (address); /** * @notice Get the vault factory's address. * @return address of the vault factory */ function VAULT_FACTORY() external view returns (address); /** * @notice Get the operator-vault opt-in service's address. * @return address of the operator-vault opt-in service */ function OPERATOR_VAULT_OPT_IN_SERVICE() external view returns (address); /** * @notice Get the operator-network opt-in service's address. * @return address of the operator-network opt-in service */ function OPERATOR_NETWORK_OPT_IN_SERVICE() external view returns (address); /** * @notice Get a gas limit for the hook. * @return value of the hook gas limit */ function HOOK_GAS_LIMIT() external view returns (uint256); /** * @notice Get a reserve gas between the gas limit check and the hook's execution. * @return value of the reserve gas */ function HOOK_RESERVE() external view returns (uint256); /** * @notice Get a hook setter's role. * @return identifier of the hook setter role */ function HOOK_SET_ROLE() external view returns (bytes32); /** * @notice Get the vault's address. * @return address of the vault */ function vault() external view returns (address); /** * @notice Get the hook's address. * @return address of the hook * @dev The hook can have arbitrary logic under certain functions, however, it doesn't affect the stake guarantees. */ function hook() external view returns (address); /** * @notice Get a particular subnetwork's maximum limit * (meaning the subnetwork is not ready to get more as a stake). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @return maximum limit of the subnetwork */ function maxNetworkLimit( bytes32 subnetwork ) external view returns (uint256); /** * @notice Get a stake that a given subnetwork could be able to slash for a certain operator at a given timestamp * until the end of the consequent epoch using hints (if no cross-slashing and no slashings by the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param timestamp time point to capture the stake at * @param hints hints for the checkpoints' indexes * @return slashable stake at the given timestamp until the end of the consequent epoch * @dev Warning: it is not safe to use timestamp >= current one for the stake capturing, as it can change later. */ function stakeAt( bytes32 subnetwork, address operator, uint48 timestamp, bytes memory hints ) external view returns (uint256); /** * @notice Get a stake that a given subnetwork will be able to slash * for a certain operator until the end of the next epoch (if no cross-slashing and no slashings by the subnetwork). * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @return slashable stake until the end of the next epoch * @dev Warning: this function is not safe to use for stake capturing, as it can change by the end of the block. */ function stake(bytes32 subnetwork, address operator) external view returns (uint256); /** * @notice Set a maximum limit for a subnetwork (how much stake the subnetwork is ready to get). * identifier identifier of the subnetwork * @param amount new maximum subnetwork's limit * @dev Only a network can call this function. */ function setMaxNetworkLimit(uint96 identifier, uint256 amount) external; /** * @notice Set a new hook. * @param hook address of the hook * @dev Only a HOOK_SET_ROLE holder can call this function. * The hook can have arbitrary logic under certain functions, however, it doesn't affect the stake guarantees. */ function setHook( address hook ) external; /** * @notice Called when a slash happens. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param slashedAmount amount of the collateral slashed * @param captureTimestamp time point when the stake was captured * @param data some additional data * @dev Only the vault's slasher can call this function. */ function onSlash( bytes32 subnetwork, address operator, uint256 slashedAmount, uint48 captureTimestamp, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IVetoSlasher { error InsufficientSlash(); error InvalidCaptureTimestamp(); error InvalidResolverSetEpochsDelay(); error InvalidVetoDuration(); error NoResolver(); error NotNetwork(); error NotResolver(); error SlashPeriodEnded(); error SlashRequestCompleted(); error SlashRequestNotExist(); error VaultNotInitialized(); error VetoPeriodEnded(); error VetoPeriodNotEnded(); /** * @notice Initial parameters needed for a slasher deployment. * @param vetoDuration duration of the veto period for a slash request * @param resolverSetEpochsDelay delay in epochs for a network to update a resolver */ struct InitParams { uint48 vetoDuration; uint256 resolverSetEpochsDelay; } /** * @notice Structure for a slash request. * @param subnetwork subnetwork that requested the slash * @param operator operator that could be slashed (if the request is not vetoed) * @param amount maximum amount of the collateral to be slashed * @param captureTimestamp time point when the stake was captured * @param vetoDeadline deadline for the resolver to veto the slash (exclusively) * @param completed if the slash was vetoed/executed */ struct SlashRequest { bytes32 subnetwork; address operator; uint256 amount; uint48 captureTimestamp; uint48 vetoDeadline; bool completed; } /** * @notice Hints for a slash request. * @param slashableStakeHints hints for the slashable stake checkpoints */ struct RequestSlashHints { bytes slashableStakeHints; } /** * @notice Hints for a slash execute. * @param captureResolverHint hint for the resolver checkpoint at the capture time * @param currentResolverHint hint for the resolver checkpoint at the current time * @param slashableStakeHints hints for the slashable stake checkpoints */ struct ExecuteSlashHints { bytes captureResolverHint; bytes currentResolverHint; bytes slashableStakeHints; } /** * @notice Hints for a slash veto. * @param captureResolverHint hint for the resolver checkpoint at the capture time * @param currentResolverHint hint for the resolver checkpoint at the current time */ struct VetoSlashHints { bytes captureResolverHint; bytes currentResolverHint; } /** * @notice Hints for a resolver set. * @param resolverHint hint for the resolver checkpoint */ struct SetResolverHints { bytes resolverHint; } /** * @notice Emitted when a slash request is created. * @param slashIndex index of the slash request * @param subnetwork subnetwork that requested the slash * @param operator operator that could be slashed (if the request is not vetoed) * @param slashAmount maximum amount of the collateral to be slashed * @param captureTimestamp time point when the stake was captured * @param vetoDeadline deadline for the resolver to veto the slash (exclusively) */ event RequestSlash( uint256 indexed slashIndex, bytes32 indexed subnetwork, address indexed operator, uint256 slashAmount, uint48 captureTimestamp, uint48 vetoDeadline ); /** * @notice Emitted when a slash request is executed. * @param slashIndex index of the slash request * @param slashedAmount amount of the collateral slashed */ event ExecuteSlash(uint256 indexed slashIndex, uint256 slashedAmount); /** * @notice Emitted when a slash request is vetoed. * @param slashIndex index of the slash request * @param resolver address of the resolver that vetoed the slash */ event VetoSlash(uint256 indexed slashIndex, address indexed resolver); /** * @notice Emitted when a resolver is set. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param resolver address of the resolver */ event SetResolver(bytes32 indexed subnetwork, address resolver); /** * @notice Get the network registry's address. * @return address of the network registry */ function NETWORK_REGISTRY() external view returns (address); /** * @notice Get a duration during which resolvers can veto slash requests. * @return duration of the veto period */ function vetoDuration() external view returns (uint48); /** * @notice Get a total number of slash requests. * @return total number of slash requests */ function slashRequestsLength() external view returns (uint256); /** * @notice Get a particular slash request. * @param slashIndex index of the slash request * @return subnetwork subnetwork that requested the slash * @return operator operator that could be slashed (if the request is not vetoed) * @return amount maximum amount of the collateral to be slashed * @return captureTimestamp time point when the stake was captured * @return vetoDeadline deadline for the resolver to veto the slash (exclusively) * @return completed if the slash was vetoed/executed */ function slashRequests( uint256 slashIndex ) external view returns ( bytes32 subnetwork, address operator, uint256 amount, uint48 captureTimestamp, uint48 vetoDeadline, bool completed ); /** * @notice Get a delay for networks in epochs to update a resolver. * @return updating resolver delay in epochs */ function resolverSetEpochsDelay() external view returns (uint256); /** * @notice Get a resolver for a given subnetwork at a particular timestamp using a hint. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param timestamp timestamp to get the resolver at * @param hints hints for the checkpoint index * @return address of the resolver */ function resolverAt(bytes32 subnetwork, uint48 timestamp, bytes memory hints) external view returns (address); /** * @notice Get a resolver for a given subnetwork using a hint. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param hint hint for the checkpoint index * @return address of the resolver */ function resolver(bytes32 subnetwork, bytes memory hint) external view returns (address); /** * @notice Request a slash using a subnetwork for a particular operator by a given amount using hints. * @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier) * @param operator address of the operator * @param amount maximum amount of the collateral to be slashed * @param captureTimestamp time point when the stake was captured * @param hints hints for checkpoints' indexes * @return slashIndex index of the slash request * @dev Only a network middleware can call this function. */ function requestSlash( bytes32 subnetwork, address operator, uint256 amount, uint48 captureTimestamp, bytes calldata hints ) external returns (uint256 slashIndex); /** * @notice Execute a slash with a given slash index using hints. * @param slashIndex index of the slash request * @param hints hints for checkpoints' indexes * @return slashedAmount amount of the collateral slashed * @dev Only a network middleware can call this function. */ function executeSlash(uint256 slashIndex, bytes calldata hints) external returns (uint256 slashedAmount); /** * @notice Veto a slash with a given slash index using hints. * @param slashIndex index of the slash request * @param hints hints for checkpoints' indexes * @dev Only a resolver can call this function. */ function vetoSlash(uint256 slashIndex, bytes calldata hints) external; /** * @notice Set a resolver for a subnetwork using hints. * identifier identifier of the subnetwork * @param resolver address of the resolver * @param hints hints for checkpoints' indexes * @dev Only a network can call this function. */ function setResolver(uint96 identifier, address resolver, bytes calldata hints) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; 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 Get if the entity is initialized. * @return if the entity is initialized */ function isInitialized() external view returns (bool); /** * @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.0.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, bytes32) { bytes32 key = map._keys.at(index); return (key, map._values[key]); } /** * @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, bytes32) { bytes32 value = map._values[key]; if (value == bytes32(0)) { return (contains(map, key), bytes32(0)); } else { return (true, value); } } /** * @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, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), uint256(value)); } /** * @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, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, uint256(value)); } /** * @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, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } /** * @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, address) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(value)))); } /** * @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, bytes32) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), value); } /** * @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, bytes32) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, value); } /** * @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, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), uint256(value)); } /** * @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, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, uint256(value)); } /** * @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, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), address(uint160(uint256(value)))); } /** * @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, address) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, address(uint160(uint256(value)))); } /** * @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, bytes32) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), value); } /** * @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, bytes32) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, value); } /** * @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, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (key, uint256(value)); } /** * @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, uint256) { (bool success, bytes32 value) = tryGet(map._inner, key); return (success, uint256(value)); } /** * @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, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (key, address(uint160(uint256(value)))); } /** * @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, address) { (bool success, bytes32 value) = tryGet(map._inner, key); return (success, address(uint160(uint256(value)))); } /** * @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 // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. 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, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[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 pragma solidity ^0.8.25; import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol"; import {Time} from "@openzeppelin/contracts/utils/types/Time.sol"; import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; library MapWithTimeData { using EnumerableMap for EnumerableMap.AddressToUintMap; error AlreadyAdded(); error NotEnabled(); error AlreadyEnabled(); uint256 private constant ENABLED_TIME_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFF; uint256 private constant DISABLED_TIME_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFF << 48; function add(EnumerableMap.AddressToUintMap storage self, address addr) internal { if (!self.set(addr, uint256(0))) { revert AlreadyAdded(); } } function disable(EnumerableMap.AddressToUintMap storage self, address addr) internal { uint256 value = self.get(addr); if (uint48(value) == 0 || uint48(value >> 48) != 0) { revert NotEnabled(); } value |= uint256(Time.timestamp()) << 48; self.set(addr, value); } function enable(EnumerableMap.AddressToUintMap storage self, address addr) internal { uint256 value = self.get(addr); if (uint48(value) != 0 && uint48(value >> 48) == 0) { revert AlreadyEnabled(); } value = uint256(Time.timestamp()); self.set(addr, value); } function atWithTimes( EnumerableMap.AddressToUintMap storage self, uint256 idx ) internal view returns (address key, uint48 enabledTime, uint48 disabledTime) { uint256 value; (key, value) = self.at(idx); enabledTime = uint48(value); disabledTime = uint48(value >> 48); } function getTimes( EnumerableMap.AddressToUintMap storage self, address addr ) internal view returns (uint48 enabledTime, uint48 disabledTime) { uint256 value = self.get(addr); enabledTime = uint48(value); disabledTime = uint48(value >> 48); } }
// 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.0.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 value) internal pure returns (uint256) { uint256 result = 0; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 1); } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + 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.0.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.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IMigratableEntity { error AlreadyInitialized(); error InvalidInitialVersion(); 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 Get if the entity is initialized. * @return if the entity is initialized */ function isInitialized() external view returns (bool); /** * @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); /** * @dev Get a burner to issue debt to (e.g., 0xdEaD or some unwrapper contract). * @return address of the burner */ function burner() external view returns (address); /** * @notice Get a delegator (it delegates the vault's stake to networks and operators). * @return address of the delegator */ function delegator() external view returns (address); /** * @notice Get a slasher (it provides networks a slashing mechanism). * @return address of the slasher */ function slasher() external view returns (address); /** * @notice Get a time point of the epoch duration set. * @return time point of the epoch duration set */ function epochDurationInit() external view returns (uint48); /** * @notice Get a duration of the vault epoch. * @return duration of the epoch */ function epochDuration() external view returns (uint48); /** * @notice Get an epoch at a given timestamp. * @param timestamp time point to get the epoch at * @return epoch at the timestamp * @dev Reverts if the timestamp is less than the start of the epoch 0. */ function epochAt( uint48 timestamp ) external view returns (uint256); /** * @notice Get a current vault epoch. * @return current epoch */ function currentEpoch() external view returns (uint256); /** * @notice Get a start of the current vault epoch. * @return start of the current epoch */ function currentEpochStart() external view returns (uint48); /** * @notice Get a start of the previous vault epoch. * @return start of the previous epoch * @dev Reverts if the current epoch is 0. */ function previousEpochStart() external view returns (uint48); /** * @notice Get a start of the next vault epoch. * @return start of the next epoch */ function nextEpochStart() external view returns (uint48); /** * @notice Get if the deposit whitelist is enabled. * @return if the deposit whitelist is enabled */ function depositWhitelist() external view returns (bool); /** * @notice Get if a given account is whitelisted as a depositor. * @param account address to check * @return if the account is whitelisted as a depositor */ function isDepositorWhitelisted( address account ) external view returns (bool); /** * @notice Get if the deposit limit is set. * @return if the deposit limit is set */ function isDepositLimit() external view returns (bool); /** * @notice Get a deposit limit (maximum amount of the collateral that can be in the vault simultaneously). * @return deposit limit */ function depositLimit() external view returns (uint256); /** * @notice Get a total number of active shares in the vault at a given timestamp using a hint. * @param timestamp time point to get the total number of active shares at * @param hint hint for the checkpoint index * @return total number of active shares at the timestamp */ function activeSharesAt(uint48 timestamp, bytes memory hint) external view returns (uint256); /** * @notice Get a total number of active shares in the vault. * @return total number of active shares */ function activeShares() external view returns (uint256); /** * @notice Get a total amount of active stake in the vault at a given timestamp using a hint. * @param timestamp time point to get the total active stake at * @param hint hint for the checkpoint index * @return total amount of active stake at the timestamp */ function activeStakeAt(uint48 timestamp, bytes memory hint) external view returns (uint256); /** * @notice Get a total amount of active stake in the vault. * @return total amount of active stake */ function activeStake() external view returns (uint256); /** * @notice Get a total number of active shares for a particular account at a given timestamp using a hint. * @param account account to get the number of active shares for * @param timestamp time point to get the number of active shares for the account at * @param hint hint for the checkpoint index * @return number of active shares for the account at the timestamp */ function activeSharesOfAt(address account, uint48 timestamp, bytes memory hint) external view returns (uint256); /** * @notice Get a number of active shares for a particular account. * @param account account to get the number of active shares for * @return number of active shares for the account */ function activeSharesOf( address account ) external view returns (uint256); /** * @notice Get a total amount of the withdrawals at a given epoch. * @param epoch epoch to get the total amount of the withdrawals at * @return total amount of the withdrawals at the epoch */ function withdrawals( uint256 epoch ) external view returns (uint256); /** * @notice Get a total number of withdrawal shares at a given epoch. * @param epoch epoch to get the total number of withdrawal shares at * @return total number of withdrawal shares at the epoch */ function withdrawalShares( uint256 epoch ) external view returns (uint256); /** * @notice Get a number of withdrawal shares for a particular account at a given epoch (zero if claimed). * @param epoch epoch to get the number of withdrawal shares for the account at * @param account account to get the number of withdrawal shares for * @return number of withdrawal shares for the account at the epoch */ function withdrawalSharesOf(uint256 epoch, address account) external view returns (uint256); /** * @notice Get if the withdrawals are claimed for a particular account at a given epoch. * @param epoch epoch to check the withdrawals for the account at * @param account account to check the withdrawals for * @return if the withdrawals are claimed for the account at the epoch */ function isWithdrawalsClaimed(uint256 epoch, address account) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; 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.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; 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)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/Checkpoints.sol) // This file was procedurally generated from scripts/generate/templates/Checkpoints.js. pragma solidity ^0.8.20; import {Math} from "../math/Math.sol"; /** * @dev This library defines the `Trace*` struct, for checkpointing values as they change at different points in * time, and later looking up past values by block number. See {Votes} as an example. * * To create a history of checkpoints define a variable type `Checkpoints.Trace*` in your contract, and store a new * checkpoint for the current transaction block using the {push} function. */ library Checkpoints { /** * @dev A value was attempted to be inserted on a past checkpoint. */ error CheckpointUnorderedInsertion(); struct Trace224 { Checkpoint224[] _checkpoints; } struct Checkpoint224 { uint32 _key; uint224 _value; } /** * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint. * * Returns previous value and new value. * * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint32).max` key set will disable the * library. */ function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) { return _insert(self._checkpoints, key, value); } /** * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if * there is none. */ function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) { uint256 len = self._checkpoints.length; uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. */ function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) { uint256 len = self._checkpoints.length; uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. * * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high * keys). */ function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) { uint256 len = self._checkpoints.length; uint256 low = 0; uint256 high = len; if (len > 5) { uint256 mid = len - Math.sqrt(len); if (key < _unsafeAccess(self._checkpoints, mid)._key) { high = mid; } else { low = mid + 1; } } uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. */ function latest(Trace224 storage self) internal view returns (uint224) { uint256 pos = self._checkpoints.length; return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value * in the most recent checkpoint. */ function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) { uint256 pos = self._checkpoints.length; if (pos == 0) { return (false, 0, 0); } else { Checkpoint224 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); return (true, ckpt._key, ckpt._value); } } /** * @dev Returns the number of checkpoint. */ function length(Trace224 storage self) internal view returns (uint256) { return self._checkpoints.length; } /** * @dev Returns checkpoint at given position. */ function at(Trace224 storage self, uint32 pos) internal view returns (Checkpoint224 memory) { return self._checkpoints[pos]; } /** * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, * or by updating the last one. */ function _insert(Checkpoint224[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) { uint256 pos = self.length; if (pos > 0) { Checkpoint224 storage last = _unsafeAccess(self, pos - 1); uint32 lastKey = last._key; uint224 lastValue = last._value; // Checkpoint keys must be non-decreasing. if (lastKey > key) { revert CheckpointUnorderedInsertion(); } // Update or push new checkpoint if (lastKey == key) { last._value = value; } else { self.push(Checkpoint224({_key: key, _value: value})); } return (lastValue, value); } else { self.push(Checkpoint224({_key: key, _value: value})); return (0, value); } } /** * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high` * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive * `high`. * * WARNING: `high` should not be greater than the array's length. */ function _upperBinaryLookup( Checkpoint224[] storage self, uint32 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key > key) { high = mid; } else { low = mid + 1; } } return high; } /** * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high` * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive * `high`. * * WARNING: `high` should not be greater than the array's length. */ function _lowerBinaryLookup( Checkpoint224[] storage self, uint32 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key < key) { low = mid + 1; } else { high = mid; } } return high; } /** * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. */ function _unsafeAccess( Checkpoint224[] storage self, uint256 pos ) private pure returns (Checkpoint224 storage result) { assembly { mstore(0, self.slot) result.slot := add(keccak256(0, 0x20), pos) } } struct Trace208 { Checkpoint208[] _checkpoints; } struct Checkpoint208 { uint48 _key; uint208 _value; } /** * @dev Pushes a (`key`, `value`) pair into a Trace208 so that it is stored as the checkpoint. * * Returns previous value and new value. * * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint48).max` key set will disable the * library. */ function push(Trace208 storage self, uint48 key, uint208 value) internal returns (uint208, uint208) { return _insert(self._checkpoints, key, value); } /** * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if * there is none. */ function lowerLookup(Trace208 storage self, uint48 key) internal view returns (uint208) { uint256 len = self._checkpoints.length; uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. */ function upperLookup(Trace208 storage self, uint48 key) internal view returns (uint208) { uint256 len = self._checkpoints.length; uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. * * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high * keys). */ function upperLookupRecent(Trace208 storage self, uint48 key) internal view returns (uint208) { uint256 len = self._checkpoints.length; uint256 low = 0; uint256 high = len; if (len > 5) { uint256 mid = len - Math.sqrt(len); if (key < _unsafeAccess(self._checkpoints, mid)._key) { high = mid; } else { low = mid + 1; } } uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. */ function latest(Trace208 storage self) internal view returns (uint208) { uint256 pos = self._checkpoints.length; return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value * in the most recent checkpoint. */ function latestCheckpoint(Trace208 storage self) internal view returns (bool exists, uint48 _key, uint208 _value) { uint256 pos = self._checkpoints.length; if (pos == 0) { return (false, 0, 0); } else { Checkpoint208 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); return (true, ckpt._key, ckpt._value); } } /** * @dev Returns the number of checkpoint. */ function length(Trace208 storage self) internal view returns (uint256) { return self._checkpoints.length; } /** * @dev Returns checkpoint at given position. */ function at(Trace208 storage self, uint32 pos) internal view returns (Checkpoint208 memory) { return self._checkpoints[pos]; } /** * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, * or by updating the last one. */ function _insert(Checkpoint208[] storage self, uint48 key, uint208 value) private returns (uint208, uint208) { uint256 pos = self.length; if (pos > 0) { Checkpoint208 storage last = _unsafeAccess(self, pos - 1); uint48 lastKey = last._key; uint208 lastValue = last._value; // Checkpoint keys must be non-decreasing. if (lastKey > key) { revert CheckpointUnorderedInsertion(); } // Update or push new checkpoint if (lastKey == key) { last._value = value; } else { self.push(Checkpoint208({_key: key, _value: value})); } return (lastValue, value); } else { self.push(Checkpoint208({_key: key, _value: value})); return (0, value); } } /** * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high` * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive * `high`. * * WARNING: `high` should not be greater than the array's length. */ function _upperBinaryLookup( Checkpoint208[] storage self, uint48 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key > key) { high = mid; } else { low = mid + 1; } } return high; } /** * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high` * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive * `high`. * * WARNING: `high` should not be greater than the array's length. */ function _lowerBinaryLookup( Checkpoint208[] storage self, uint48 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key < key) { low = mid + 1; } else { high = mid; } } return high; } /** * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. */ function _unsafeAccess( Checkpoint208[] storage self, uint256 pos ) private pure returns (Checkpoint208 storage result) { assembly { mstore(0, self.slot) result.slot := add(keccak256(0, 0x20), pos) } } struct Trace160 { Checkpoint160[] _checkpoints; } struct Checkpoint160 { uint96 _key; uint160 _value; } /** * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint. * * Returns previous value and new value. * * IMPORTANT: Never accept `key` as a user input, since an arbitrary `type(uint96).max` key set will disable the * library. */ function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) { return _insert(self._checkpoints, key, value); } /** * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if * there is none. */ function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) { uint256 len = self._checkpoints.length; uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. */ function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) { uint256 len = self._checkpoints.length; uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero * if there is none. * * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high * keys). */ function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) { uint256 len = self._checkpoints.length; uint256 low = 0; uint256 high = len; if (len > 5) { uint256 mid = len - Math.sqrt(len); if (key < _unsafeAccess(self._checkpoints, mid)._key) { high = mid; } else { low = mid + 1; } } uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. */ function latest(Trace160 storage self) internal view returns (uint160) { uint256 pos = self._checkpoints.length; return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; } /** * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value * in the most recent checkpoint. */ function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) { uint256 pos = self._checkpoints.length; if (pos == 0) { return (false, 0, 0); } else { Checkpoint160 storage ckpt = _unsafeAccess(self._checkpoints, pos - 1); return (true, ckpt._key, ckpt._value); } } /** * @dev Returns the number of checkpoint. */ function length(Trace160 storage self) internal view returns (uint256) { return self._checkpoints.length; } /** * @dev Returns checkpoint at given position. */ function at(Trace160 storage self, uint32 pos) internal view returns (Checkpoint160 memory) { return self._checkpoints[pos]; } /** * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, * or by updating the last one. */ function _insert(Checkpoint160[] storage self, uint96 key, uint160 value) private returns (uint160, uint160) { uint256 pos = self.length; if (pos > 0) { Checkpoint160 storage last = _unsafeAccess(self, pos - 1); uint96 lastKey = last._key; uint160 lastValue = last._value; // Checkpoint keys must be non-decreasing. if (lastKey > key) { revert CheckpointUnorderedInsertion(); } // Update or push new checkpoint if (lastKey == key) { last._value = value; } else { self.push(Checkpoint160({_key: key, _value: value})); } return (lastValue, value); } else { self.push(Checkpoint160({_key: key, _value: value})); return (0, value); } } /** * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or `high` * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive * `high`. * * WARNING: `high` should not be greater than the array's length. */ function _upperBinaryLookup( Checkpoint160[] storage self, uint96 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key > key) { high = mid; } else { low = mid + 1; } } return high; } /** * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or `high` * if there is none. `low` and `high` define a section where to do the search, with inclusive `low` and exclusive * `high`. * * WARNING: `high` should not be greater than the array's length. */ function _lowerBinaryLookup( Checkpoint160[] storage self, uint96 key, uint256 low, uint256 high ) private view returns (uint256) { while (low < high) { uint256 mid = Math.average(low, high); if (_unsafeAccess(self, mid)._key < key) { low = mid + 1; } else { high = mid; } } return high; } /** * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. */ function _unsafeAccess( Checkpoint160[] storage self, uint256 pos ) private pure returns (Checkpoint160 storage result) { assembly { mstore(0, self.slot) result.slot := add(keccak256(0, 0x20), pos) } } }
// SPDX-License-Identifier: MIT 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]. */ // 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.0.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/", "@symbiotic/=lib/symbiotic/src/", "forge-std/=lib/forge-std/src/", "@openzeppelin/contracts-upgradeable/=lib/symbiotic/lib/openzeppelin-contracts-upgradeable/contracts/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin-contracts-upgradeable/=lib/symbiotic/lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "symbiotic/=lib/symbiotic/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_network","type":"address"},{"internalType":"address","name":"_operatorRegistry","type":"address"},{"internalType":"address","name":"_vaultRegistry","type":"address"},{"internalType":"address","name":"_operatorNetOptin","type":"address"},{"internalType":"uint48","name":"_epochDuration","type":"uint48"},{"internalType":"uint48","name":"_slashingWindow","type":"uint48"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyAdded","type":"error"},{"inputs":[],"name":"AlreadyAdded","type":"error"},{"inputs":[],"name":"AlreadyEnabled","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":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"EnumerableMapNonexistentKey","type":"error"},{"inputs":[],"name":"InvalidEpoch","type":"error"},{"inputs":[],"name":"InvalidOperatorAddress","type":"error"},{"inputs":[],"name":"InvalidSubnetworksCnt","type":"error"},{"inputs":[],"name":"NotEnabled","type":"error"},{"inputs":[],"name":"NotVault","type":"error"},{"inputs":[],"name":"OperarorGracePeriodNotPassed","type":"error"},{"inputs":[],"name":"OperatorAlreadyRegistered","type":"error"},{"inputs":[],"name":"OperatorNotOptedIn","type":"error"},{"inputs":[],"name":"OperatorNotRegistered","type":"error"},{"inputs":[],"name":"OperatorNotRegisteredInRegistry","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[],"name":"SlashingWindowTooShort","type":"error"},{"inputs":[],"name":"TooOldEpoch","type":"error"},{"inputs":[],"name":"VaultAlreadyRegistered","type":"error"},{"inputs":[],"name":"VaultEpochTooShort","type":"error"},{"inputs":[],"name":"VaultGracePeriodNotPassed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operatorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"operatorIndex","type":"uint256"}],"name":"OperatorRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operatorAddress","type":"address"}],"name":"OperatorUnregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"taskId","type":"uint256"},{"indexed":false,"internalType":"string","name":"message","type":"string"},{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"operatorIndex","type":"uint256"}],"name":"TaskCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"taskId","type":"uint256"},{"indexed":false,"internalType":"address","name":"operator","type":"address"}],"name":"TaskSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"vaultAddress","type":"address"}],"name":"VaultRegistered","type":"event"},{"inputs":[],"name":"EPOCH_DURATION","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NETWORK","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_NET_OPTIN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLASHING_WINDOW","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"START_TIME","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_REGISTRY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint48","name":"epoch","type":"uint48"}],"name":"calcAndCacheStakes","outputs":[{"internalType":"uint256","name":"totalStake","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_message","type":"string"}],"name":"createTask","outputs":[{"internalType":"uint256","name":"taskId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentEpoch","outputs":[{"internalType":"uint48","name":"epoch","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint48","name":"timestamp","type":"uint48"}],"name":"getEpochAtTs","outputs":[{"internalType":"uint48","name":"epoch","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint48","name":"epoch","type":"uint48"}],"name":"getEpochStartTs","outputs":[{"internalType":"uint48","name":"timestamp","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operatorAddress","type":"address"}],"name":"getOperatorIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOperatorSet","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint48","name":"epoch","type":"uint48"}],"name":"getOperatorStake","outputs":[{"internalType":"uint256","name":"stake","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRegisteredVaults","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint48","name":"epoch","type":"uint48"}],"name":"getTotalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultAddress","type":"address"}],"name":"isVaultRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"operatorSet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint48","name":"","type":"uint48"},{"internalType":"address","name":"","type":"address"}],"name":"operatorStakeCache","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"pauseOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"pauseVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operatorAddress","type":"address"}],"name":"registerOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vaultAddress","type":"address"}],"name":"registerVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_subnetworksCnt","type":"uint256"}],"name":"setSubnetworksCnt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_taskId","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"submitTask","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subnetworksCnt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tasks","outputs":[{"internalType":"string","name":"message","type":"string"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"operatorIndex","type":"uint256"},{"internalType":"bool","name":"completed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint48","name":"","type":"uint48"}],"name":"totalStakeCache","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint48","name":"","type":"uint48"}],"name":"totalStakeCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"unpauseOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"unpauseVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operatorAddress","type":"address"}],"name":"unregisterOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"vault","type":"address"}],"name":"unregisterVault","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61016060405234801561001157600080fd5b50604051612c80380380612c80833981016040819052610030916101b3565b338061005757604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b610060816100ea565b508165ffffffffffff168165ffffffffffff1610156100925760405163188a354160e31b815260040160405180910390fd5b6001600160a01b0380871660805285811660a05284811660c052831660e05265ffffffffffff808316610120528116610100526100cd61013a565b65ffffffffffff1661014052505060016010555061022792505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006101454261014a565b905090565b600065ffffffffffff82111561017d576040516306dfcc6560e41b8152603060048201526024810183905260440161004e565b5090565b80516001600160a01b038116811461019857600080fd5b919050565b805165ffffffffffff8116811461019857600080fd5b60008060008060008060c087890312156101cc57600080fd5b6101d587610181565b95506101e360208801610181565b94506101f160408801610181565b93506101ff60608801610181565b925061020d6080880161019d565b915061021b60a0880161019d565b90509295509295509295565b60805160a05160c05160e05161010051610120516101405161299d6102e360003960008181610585015281816107d001526115af01526000818161053b015281816107a5015261158b0152600081816102e3015281816108310152818161089e01528181611010015281816114f50152611c2b0152600081816104c80152610b700152600081816102310152610dbb0152600081816104070152610aa101526000818161046d01528181610b48015261123c015261299d6000f3fe608060405234801561001057600080fd5b50600436106102275760003560e01c806383ce0322116101305780639d94a1e3116100b8578063bd3b40601161007c578063bd3b406014610565578063c0bd6f9e1461056d578063ddaa26ad14610580578063ee3738ca146105a7578063f2fde38b146105d257600080fd5b80639d94a1e3146104fd5780639ee5006c146105105780639fee2cdb14610523578063a70b9f0c14610536578063b97dd9e21461055d57600080fd5b80638759e6d1116100ff5780638759e6d1146104685780638d9776721461048f5780638da5cb5b146104b257806393fe3889146104c357806396115bc2146104ea57600080fd5b806383ce03221461040257806383f582b71461042957806384ca5f7d1461044c578063875461371461045f57600080fd5b8063321520f4116101b357806367ccd1cb1161018257806367ccd1cb146103ae5780636a400fe7146103c15780636a5af20b146103d4578063715018a6146103e757806372f9adab146103ef57600080fd5b8063321520f4146103535780633682a4501461037357806336917a4c146103865780633eb22c951461039957600080fd5b806322207cc7116101fa57806322207cc7146102de5780632633b70f14610305578063282795931461031a5780632e5aaf331461032d5780632efbab2c1461034057600080fd5b806302ace7fe1461022c578063105a88e314610270578063111002aa1461029357806311369f0f146102b4575b600080fd5b6102537f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61028361027e36600461226c565b6105e5565b6040519015158152602001610267565b6102a66102a136600461229f565b6105f8565b604051908152602001610267565b6102c76102c2366004612364565b61079e565b60405165ffffffffffff9091168152602001610267565b6102c77f000000000000000000000000000000000000000000000000000000000000000081565b61031861031336600461226c565b6107f4565b005b6102a6610328366004612364565b61088e565b61031861033b36600461226c565b610a01565b61031861034e36600461226c565b610a17565b6102a6610361366004612364565b600d6020526000908152604090205481565b61031861038136600461226c565b610a2a565b610253610394366004612381565b610cdf565b6103a1610d09565b604051610267919061239a565b6103186103bc36600461226c565b610d6b565b6102a66103cf36600461226c565b6110ae565b6103186103e2366004612381565b6110bb565b6103186110ea565b6103186103fd36600461226c565b6110fe565b6102537f000000000000000000000000000000000000000000000000000000000000000081565b610283610437366004612364565b600e6020526000908152604090205460ff1681565b6102a661045a3660046123e7565b611111565b6102a660105481565b6102537f000000000000000000000000000000000000000000000000000000000000000081565b6104a261049d366004612381565b611318565b6040516102679493929190612466565b6000546001600160a01b0316610253565b6102537f000000000000000000000000000000000000000000000000000000000000000081565b6103186104f836600461226c565b6113e5565b6102c761050b366004612364565b611587565b61031861051e366004612497565b6115de565b6102a6610531366004612364565b61188b565b6102c77f000000000000000000000000000000000000000000000000000000000000000081565b6102c76118cf565b6103a16118e1565b61031861057b36600461226c565b6118ed565b6102c77f000000000000000000000000000000000000000000000000000000000000000081565b6102a66105b5366004612513565b600f60209081526000928352604080842090915290825290205481565b6103186105e036600461226c565b611900565b60006105f260028361193b565b92915050565b60008082511161064f5760405162461bcd60e51b815260206004820152601760248201527f4d6573736167652063616e6e6f7420626520656d70747900000000000000000060448201526064015b60405180910390fd5b60055461069e5760405162461bcd60e51b815260206004820152601760248201527f4e6f206f70657261746f727320726567697374657265640000000000000000006044820152606401610646565b60055443906000906106b09083612557565b604080516080810182528681526020810185905290810182905260006060820181905260018054808201825591528151929350909182916004027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190819061071990826125f5565b506020820151600182810191909155604083015160028301556060909201516003909101805460ff1916911515919091179055805461075891906126cb565b9350837fb8bf6379f90c5d70f70429564879392d448aab0a6849cb01675122756962e84586858560405161078e939291906126de565b60405180910390a2505050919050565b60006107ca7f000000000000000000000000000000000000000000000000000000000000000083612703565b6105f2907f0000000000000000000000000000000000000000000000000000000000000000612725565b6107fc611957565b6000610809600283611984565b91505065ffffffffffff8116158061086057506108246119a1565b65ffffffffffff166108567f000000000000000000000000000000000000000000000000000000000000000083612725565b65ffffffffffff16115b1561087e576040516347a11ef760e11b815260040160405180910390fd5b6108896002836119ac565b505050565b60008061089a8361079e565b90507f00000000000000000000000000000000000000000000000000000000000000006108c56119a1565b6108cf9190612744565b65ffffffffffff168165ffffffffffff1610156108ff576040516312c7b10160e11b815260040160405180910390fd5b6109076119a1565b65ffffffffffff168165ffffffffffff1611156109375760405163d5b25b6360e01b815260040160405180910390fd5b60005b61094460096119c1565b8110156109cc576000808061095a6009856119cc565b92509250925061096b8282876119ee565b610977575050506109c4565b60006109838487611111565b65ffffffffffff89166000908152600f602090815260408083206001600160a01b0389168452909152902081905590506109bd8188612763565b9650505050505b60010161093a565b505065ffffffffffff9091166000908152600e60209081526040808320805460ff19166001179055600d909152902081905590565b610a09611957565b610a14600982611a4b565b50565b610a1f611957565b610a14600282611a4b565b610a32611957565b610a3d60068261193b565b15610a5b576040516342ee68b560e01b815260040160405180910390fd5b6001600160a01b038116610a825760405163eb32d3bf60e01b815260040160405180910390fd5b6040516302910f8b60e31b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906314887c5890602401602060405180830381865afa158015610ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0c9190612776565b610b295760405163d84d635760e01b815260040160405180910390fd5b6040516308834cb560e21b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063220d32d490604401602060405180830381865afa158015610bb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdb9190612776565b610bf857604051634d1cc09f60e11b815260040160405180910390fd5b600580546001808201835560008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db090910180546001600160a01b0319166001600160a01b0385161790559054610c60918391610c5791906126cb565b60069190611abb565b50610c6c600982611ad1565b610c77600982611a4b565b6001600160a01b0381166000818152600c60205260409020805460ff191660019081179091556005547fbc11617e575d658c74e921c8df22f8e48566072fa78145a6cfe18420bf8d0c4e91610ccb916126cb565b60405190815260200160405180910390a250565b60058181548110610cef57600080fd5b6000918252602090912001546001600160a01b0316905081565b60606005805480602002602001604051908101604052809291908181526020018280548015610d6157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d43575b5050505050905090565b610d73611957565b610d7e60028261193b565b15610d9c576040516324ec133760e11b815260040160405180910390fd5b6040516302910f8b60e31b81526001600160a01b0382811660048301527f000000000000000000000000000000000000000000000000000000000000000016906314887c5890602401602060405180830381865afa158015610e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e269190612776565b610e43576040516362df054560e01b815260040160405180910390fd5b6000816001600160a01b0316634ff0876a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea791906127ae565b90506000826001600160a01b031663b13442716040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0d91906127cb565b90506001600160a01b03811615801590610f9a5750600165ffffffffffff16816001600160a01b031663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8e91906127e8565b67ffffffffffffffff16145b1561100e57806001600160a01b031663e054e08b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fdd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100191906127ae565b61100b9083612744565b91505b7f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff168265ffffffffffff16101561105f5760405163121f507960e11b815260040160405180910390fd5b61106a600284611ad1565b611075600284611a4b565b6040516001600160a01b038416907f8e0930709528779f1112249aac8fcca15dbb9c595db31092c7bc7f954b56793390600090a2505050565b60006105f2600683611afe565b6110c3611957565b80601054106110e55760405163e1115e0160e01b815260040160405180910390fd5b601055565b6110f2611957565b6110fc6000611b13565b565b611106611957565b610a14600982611b63565b65ffffffffffff81166000908152600e602052604081205460ff1615611163575065ffffffffffff81166000908152600f602090815260408083206001600160a01b03861684529091529020546105f2565b600061116e8361079e565b905060005b61117d60026119c1565b81101561131057600080806111936002856119cc565b9250925092506111a48282876119ee565b6111b057505050611308565b60005b601054816001600160601b0316101561130357836001600160a01b031663ce9b79306040518163ffffffff1660e01b8152600401602060405180830381865afa158015611204573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122891906127cb565b6001600160a01b031663e02f6937611272837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611bcf90919063ffffffff16565b604080516000815260208101918290526001600160e01b031960e085901b169091526112a691908d908b9060248101612812565b602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190612854565b6112f19088612763565b96506112fc8161286d565b90506111b3565b505050505b600101611173565b505092915050565b6001818154811061132857600080fd5b906000526020600020906004020160009150905080600001805461134b9061256b565b80601f01602080910402602001604051908101604052809291908181526020018280546113779061256b565b80156113c45780601f10611399576101008083540402835291602001916113c4565b820191906000526020600020905b8154815290600101906020018083116113a757829003601f168201915b50505050600183015460028401546003909401549293909290915060ff1684565b6113ed611957565b6001600160a01b0381166114435760405162461bcd60e51b815260206004820152601860248201527f496e76616c6964206f70657261746f72206164647265737300000000000000006044820152606401610646565b6000611450600683611afe565b9050806000036114a25760405162461bcd60e51b815260206004820152601760248201527f4f70657261746f72206e6f7420726567697374657265640000000000000000006044820152606401610646565b6001600160a01b0382166000908152600c60205260408120805460ff191690556114cd600984611984565b91505065ffffffffffff8116158061152457506114e86119a1565b65ffffffffffff1661151a7f000000000000000000000000000000000000000000000000000000000000000083612725565b65ffffffffffff16115b15611542576040516377a2efc960e01b815260040160405180910390fd5b61154d6009846119ac565b506040516001600160a01b038416907f6f42117a557500c705ddf040a619d86f39101e6b74ac20d7b3e5943ba473fc7f90600090a2505050565b60007f00000000000000000000000000000000000000000000000000000000000000006115d47f000000000000000000000000000000000000000000000000000000000000000084612744565b6105f29190612893565b6115e960063361193b565b6116415760405162461bcd60e51b815260206004820152602360248201527f43616c6c6572206973206e6f7420612072656769737465726564206f706572616044820152623a37b960e91b6064820152608401610646565b60015483106116845760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d185cdac81251608a1b6044820152606401610646565b600060018481548110611699576116996128b8565b60009182526020822060049091020191506116b5600633611afe565b9050808260020154146117155760405162461bcd60e51b815260206004820152602260248201527f5461736b206e6f742061737369676e656420746f2074686973206f706572617460448201526137b960f11b6064820152608401610646565b600182015460405160009161173091859189916020016128ce565b6040516020818303038152906040528051906020012090506000611781827f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b905060006117c787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508693925050611bf19050565b90506001600160a01b03811633146118155760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610646565b6001808981548110611829576118296128b8565b600091825260209182902060049190910201600301805460ff19169215159290921790915560405133815289917f18b7d306cc91d617b756cefb57e5c27c82a5dce9d470e537b52f823672212642910160405180910390a25050505050505050565b65ffffffffffff81166000908152600e602052604081205460ff16156118c6575065ffffffffffff166000908152600d602052604090205490565b6105f282611c1b565b60006118dc61050b6119a1565b905090565b60606118dc6002611d32565b6118f5611957565b610a14600282611b63565b611908611957565b6001600160a01b03811661193257604051631e4fbdf760e01b815260006004820152602401610646565b610a1481611b13565b6000611950836001600160a01b038416611d3f565b9392505050565b6000546001600160a01b031633146110fc5760405163118cdaa760e01b8152336004820152602401610646565b600080806119928585611afe565b95603087901c95509350505050565b60006118dc42611d4b565b6000611950836001600160a01b038416611d82565b60006105f282611d9f565b60008080806119db8686611daa565b9097909650603087901c95509350505050565b600065ffffffffffff841615801590611a1757508165ffffffffffff168465ffffffffffff1611155b8015611a43575065ffffffffffff83161580611a4357508165ffffffffffff168365ffffffffffff1610155b949350505050565b6000611a578383611afe565b905065ffffffffffff811615801590611a7a575065ffffffffffff603082901c16155b15611a9857604051637952fbad60e11b815260040160405180910390fd5b611aa06119a1565b65ffffffffffff169050611ab5838383611abb565b50505050565b6000611a43846001600160a01b03851684611dc6565b611add82826000611abb565b611afa5760405163f411c32760e01b815260040160405180910390fd5b5050565b6000611950836001600160a01b038416611de3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000611b6f8383611afe565b905065ffffffffffff81161580611b91575065ffffffffffff603082901c1615155b15611baf57604051633f54562b60e11b815260040160405180910390fd5b6030611bb96119a1565b65ffffffffffff16901b17611ab5838383611abb565b6001600160601b031660609190911b6bffffffffffffffffffffffff19161790565b600080600080611c018686611e2a565b925092509250611c118282611e77565b5090949350505050565b600080611c278361079e565b90507f0000000000000000000000000000000000000000000000000000000000000000611c526119a1565b611c5c9190612744565b65ffffffffffff168165ffffffffffff161015611c8c576040516312c7b10160e11b815260040160405180910390fd5b611c946119a1565b65ffffffffffff168165ffffffffffff161115611cc45760405163d5b25b6360e01b815260040160405180910390fd5b60005b611cd160096119c1565b811015611d2b5760008080611ce76009856119cc565b925092509250611cf88282876119ee565b611d0457505050611d23565b6000611d108487611111565b9050611d1c8188612763565b9650505050505b600101611cc7565b5050919050565b6060600061195083611f30565b60006119508383611f3b565b600065ffffffffffff821115611d7e576040516306dfcc6560e41b81526030600482015260248101839052604401610646565b5090565b600081815260028301602052604081208190556119508383611f53565b60006105f282611f5f565b6000808080611db98686611f69565b9097909650945050505050565b60008281526002840160205260408120829055611a438484611f94565b600081815260028301602052604081205480158015611e095750611e078484611d3f565b155b156119505760405163015ab34360e11b815260048101849052602401610646565b60008060008351604103611e645760208401516040850151606086015160001a611e5688828585611fa0565b955095509550505050611e70565b50508151600091506002905b9250925092565b6000826003811115611e8b57611e8b612798565b03611e94575050565b6001826003811115611ea857611ea8612798565b03611ec65760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115611eda57611eda612798565b03611efb5760405163fce698f760e01b815260048101829052602401610646565b6003826003811115611f0f57611f0f612798565b03611afa576040516335e2f38360e21b815260048101829052602401610646565b60606105f28261206f565b60008181526001830160205260408120541515611950565b6000611950838361207c565b60006105f2825490565b60008080611f778585612176565b600081815260029690960160205260409095205494959350505050565b60006119508383612182565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611fdb5750600091506003905082612065565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561202f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661205b57506000925060019150829050612065565b9250600091508190505b9450945094915050565b60606000611950836121d1565b600081815260018301602052604081205480156121655760006120a06001836126cb565b85549091506000906120b4906001906126cb565b90508082146121195760008660000182815481106120d4576120d46128b8565b90600052602060002001549050808760000184815481106120f7576120f76128b8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061212a5761212a612951565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f2565b60009150506105f2565b5092915050565b6000611950838361222d565b60008181526001830160205260408120546121c9575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f2565b5060006105f2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561222157602002820191906000526020600020905b81548152602001906001019080831161220d575b50505050509050919050565b6000826000018281548110612244576122446128b8565b9060005260206000200154905092915050565b6001600160a01b0381168114610a1457600080fd5b60006020828403121561227e57600080fd5b813561195081612257565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156122b157600080fd5b813567ffffffffffffffff808211156122c957600080fd5b818401915084601f8301126122dd57600080fd5b8135818111156122ef576122ef612289565b604051601f8201601f19908116603f0116810190838211818310171561231757612317612289565b8160405282815287602084870101111561233057600080fd5b826020860160208301376000928101602001929092525095945050505050565b65ffffffffffff81168114610a1457600080fd5b60006020828403121561237657600080fd5b813561195081612350565b60006020828403121561239357600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156123db5783516001600160a01b0316835292840192918401916001016123b6565b50909695505050505050565b600080604083850312156123fa57600080fd5b823561240581612257565b9150602083013561241581612350565b809150509250929050565b6000815180845260005b818110156124465760208185018101518683018201520161242a565b506000602082860101526020601f19601f83011685010191505092915050565b6080815260006124796080830187612420565b60208301959095525060408101929092521515606090910152919050565b6000806000604084860312156124ac57600080fd5b83359250602084013567ffffffffffffffff808211156124cb57600080fd5b818601915086601f8301126124df57600080fd5b8135818111156124ee57600080fd5b87602082850101111561250057600080fd5b6020830194508093505050509250925092565b6000806040838503121561252657600080fd5b823561253181612350565b9150602083013561241581612257565b634e487b7160e01b600052601260045260246000fd5b60008261256657612566612541565b500690565b600181811c9082168061257f57607f821691505b60208210810361259f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610889576000816000526020600020601f850160051c810160208610156125ce5750805b601f850160051c820191505b818110156125ed578281556001016125da565b505050505050565b815167ffffffffffffffff81111561260f5761260f612289565b6126238161261d845461256b565b846125a5565b602080601f83116001811461265857600084156126405750858301515b600019600386901b1c1916600185901b1785556125ed565b600085815260208120601f198616915b8281101561268757888601518255948401946001909101908401612668565b50858210156126a55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b818103818111156105f2576105f26126b5565b6060815260006126f16060830186612420565b60208301949094525060400152919050565b65ffffffffffff818116838216028082169190828114611310576113106126b5565b65ffffffffffff81811683821601908082111561216f5761216f6126b5565b65ffffffffffff82811682821603908082111561216f5761216f6126b5565b808201808211156105f2576105f26126b5565b60006020828403121561278857600080fd5b8151801515811461195057600080fd5b634e487b7160e01b600052602160045260246000fd5b6000602082840312156127c057600080fd5b815161195081612350565b6000602082840312156127dd57600080fd5b815161195081612257565b6000602082840312156127fa57600080fd5b815167ffffffffffffffff8116811461195057600080fd5b8481526001600160a01b038416602082015265ffffffffffff8316604082015260806060820181905260009061284a90830184612420565b9695505050505050565b60006020828403121561286657600080fd5b5051919050565b60006001600160601b03808316818103612889576128896126b5565b6001019392505050565b600065ffffffffffff808416806128ac576128ac612541565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b60008085546128dc8161256b565b600182811680156128f4576001811461290957612938565b60ff1984168752821515830287019450612938565b8960005260208060002060005b8581101561292f5781548a820152908401908201612916565b50505082870194505b5050509481526020810193909352505060400192915050565b634e487b7160e01b600052603160045260246000fdfea264697066735822122060d14e1809bbd3f20c9c21b505974d74f63fbcd2108d50619bf2d12c1d92e5d664736f6c63430008190033000000000000000000000000cb2fb374ff22ed8d1046a80601170c5e0b745ad7000000000000000000000000a02c55a6306c859517a064fb34d48dfb773a4a520000000000000000000000005035c15f3cb4364cf2cf35ca53e3d6fc45fc8899000000000000000000000000973ba45986ff71742129d23c4138bb3fad4f13a500000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000015180
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102275760003560e01c806383ce0322116101305780639d94a1e3116100b8578063bd3b40601161007c578063bd3b406014610565578063c0bd6f9e1461056d578063ddaa26ad14610580578063ee3738ca146105a7578063f2fde38b146105d257600080fd5b80639d94a1e3146104fd5780639ee5006c146105105780639fee2cdb14610523578063a70b9f0c14610536578063b97dd9e21461055d57600080fd5b80638759e6d1116100ff5780638759e6d1146104685780638d9776721461048f5780638da5cb5b146104b257806393fe3889146104c357806396115bc2146104ea57600080fd5b806383ce03221461040257806383f582b71461042957806384ca5f7d1461044c578063875461371461045f57600080fd5b8063321520f4116101b357806367ccd1cb1161018257806367ccd1cb146103ae5780636a400fe7146103c15780636a5af20b146103d4578063715018a6146103e757806372f9adab146103ef57600080fd5b8063321520f4146103535780633682a4501461037357806336917a4c146103865780633eb22c951461039957600080fd5b806322207cc7116101fa57806322207cc7146102de5780632633b70f14610305578063282795931461031a5780632e5aaf331461032d5780632efbab2c1461034057600080fd5b806302ace7fe1461022c578063105a88e314610270578063111002aa1461029357806311369f0f146102b4575b600080fd5b6102537f0000000000000000000000005035c15f3cb4364cf2cf35ca53e3d6fc45fc889981565b6040516001600160a01b0390911681526020015b60405180910390f35b61028361027e36600461226c565b6105e5565b6040519015158152602001610267565b6102a66102a136600461229f565b6105f8565b604051908152602001610267565b6102c76102c2366004612364565b61079e565b60405165ffffffffffff9091168152602001610267565b6102c77f000000000000000000000000000000000000000000000000000000000001518081565b61031861031336600461226c565b6107f4565b005b6102a6610328366004612364565b61088e565b61031861033b36600461226c565b610a01565b61031861034e36600461226c565b610a17565b6102a6610361366004612364565b600d6020526000908152604090205481565b61031861038136600461226c565b610a2a565b610253610394366004612381565b610cdf565b6103a1610d09565b604051610267919061239a565b6103186103bc36600461226c565b610d6b565b6102a66103cf36600461226c565b6110ae565b6103186103e2366004612381565b6110bb565b6103186110ea565b6103186103fd36600461226c565b6110fe565b6102537f000000000000000000000000a02c55a6306c859517a064fb34d48dfb773a4a5281565b610283610437366004612364565b600e6020526000908152604090205460ff1681565b6102a661045a3660046123e7565b611111565b6102a660105481565b6102537f000000000000000000000000cb2fb374ff22ed8d1046a80601170c5e0b745ad781565b6104a261049d366004612381565b611318565b6040516102679493929190612466565b6000546001600160a01b0316610253565b6102537f000000000000000000000000973ba45986ff71742129d23c4138bb3fad4f13a581565b6103186104f836600461226c565b6113e5565b6102c761050b366004612364565b611587565b61031861051e366004612497565b6115de565b6102a6610531366004612364565b61188b565b6102c77f000000000000000000000000000000000000000000000000000000000000001881565b6102c76118cf565b6103a16118e1565b61031861057b36600461226c565b6118ed565b6102c77f0000000000000000000000000000000000000000000000000000000066f24a2081565b6102a66105b5366004612513565b600f60209081526000928352604080842090915290825290205481565b6103186105e036600461226c565b611900565b60006105f260028361193b565b92915050565b60008082511161064f5760405162461bcd60e51b815260206004820152601760248201527f4d6573736167652063616e6e6f7420626520656d70747900000000000000000060448201526064015b60405180910390fd5b60055461069e5760405162461bcd60e51b815260206004820152601760248201527f4e6f206f70657261746f727320726567697374657265640000000000000000006044820152606401610646565b60055443906000906106b09083612557565b604080516080810182528681526020810185905290810182905260006060820181905260018054808201825591528151929350909182916004027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190819061071990826125f5565b506020820151600182810191909155604083015160028301556060909201516003909101805460ff1916911515919091179055805461075891906126cb565b9350837fb8bf6379f90c5d70f70429564879392d448aab0a6849cb01675122756962e84586858560405161078e939291906126de565b60405180910390a2505050919050565b60006107ca7f000000000000000000000000000000000000000000000000000000000000001883612703565b6105f2907f0000000000000000000000000000000000000000000000000000000066f24a20612725565b6107fc611957565b6000610809600283611984565b91505065ffffffffffff8116158061086057506108246119a1565b65ffffffffffff166108567f000000000000000000000000000000000000000000000000000000000001518083612725565b65ffffffffffff16115b1561087e576040516347a11ef760e11b815260040160405180910390fd5b6108896002836119ac565b505050565b60008061089a8361079e565b90507f00000000000000000000000000000000000000000000000000000000000151806108c56119a1565b6108cf9190612744565b65ffffffffffff168165ffffffffffff1610156108ff576040516312c7b10160e11b815260040160405180910390fd5b6109076119a1565b65ffffffffffff168165ffffffffffff1611156109375760405163d5b25b6360e01b815260040160405180910390fd5b60005b61094460096119c1565b8110156109cc576000808061095a6009856119cc565b92509250925061096b8282876119ee565b610977575050506109c4565b60006109838487611111565b65ffffffffffff89166000908152600f602090815260408083206001600160a01b0389168452909152902081905590506109bd8188612763565b9650505050505b60010161093a565b505065ffffffffffff9091166000908152600e60209081526040808320805460ff19166001179055600d909152902081905590565b610a09611957565b610a14600982611a4b565b50565b610a1f611957565b610a14600282611a4b565b610a32611957565b610a3d60068261193b565b15610a5b576040516342ee68b560e01b815260040160405180910390fd5b6001600160a01b038116610a825760405163eb32d3bf60e01b815260040160405180910390fd5b6040516302910f8b60e31b81526001600160a01b0382811660048301527f000000000000000000000000a02c55a6306c859517a064fb34d48dfb773a4a5216906314887c5890602401602060405180830381865afa158015610ae8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0c9190612776565b610b295760405163d84d635760e01b815260040160405180910390fd5b6040516308834cb560e21b81526001600160a01b0382811660048301527f000000000000000000000000cb2fb374ff22ed8d1046a80601170c5e0b745ad7811660248301527f000000000000000000000000973ba45986ff71742129d23c4138bb3fad4f13a5169063220d32d490604401602060405180830381865afa158015610bb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdb9190612776565b610bf857604051634d1cc09f60e11b815260040160405180910390fd5b600580546001808201835560008390527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db090910180546001600160a01b0319166001600160a01b0385161790559054610c60918391610c5791906126cb565b60069190611abb565b50610c6c600982611ad1565b610c77600982611a4b565b6001600160a01b0381166000818152600c60205260409020805460ff191660019081179091556005547fbc11617e575d658c74e921c8df22f8e48566072fa78145a6cfe18420bf8d0c4e91610ccb916126cb565b60405190815260200160405180910390a250565b60058181548110610cef57600080fd5b6000918252602090912001546001600160a01b0316905081565b60606005805480602002602001604051908101604052809291908181526020018280548015610d6157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d43575b5050505050905090565b610d73611957565b610d7e60028261193b565b15610d9c576040516324ec133760e11b815260040160405180910390fd5b6040516302910f8b60e31b81526001600160a01b0382811660048301527f0000000000000000000000005035c15f3cb4364cf2cf35ca53e3d6fc45fc889916906314887c5890602401602060405180830381865afa158015610e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e269190612776565b610e43576040516362df054560e01b815260040160405180910390fd5b6000816001600160a01b0316634ff0876a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea791906127ae565b90506000826001600160a01b031663b13442716040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ee9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0d91906127cb565b90506001600160a01b03811615801590610f9a5750600165ffffffffffff16816001600160a01b031663bb24fe8a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8e91906127e8565b67ffffffffffffffff16145b1561100e57806001600160a01b031663e054e08b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fdd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100191906127ae565b61100b9083612744565b91505b7f000000000000000000000000000000000000000000000000000000000001518065ffffffffffff168265ffffffffffff16101561105f5760405163121f507960e11b815260040160405180910390fd5b61106a600284611ad1565b611075600284611a4b565b6040516001600160a01b038416907f8e0930709528779f1112249aac8fcca15dbb9c595db31092c7bc7f954b56793390600090a2505050565b60006105f2600683611afe565b6110c3611957565b80601054106110e55760405163e1115e0160e01b815260040160405180910390fd5b601055565b6110f2611957565b6110fc6000611b13565b565b611106611957565b610a14600982611b63565b65ffffffffffff81166000908152600e602052604081205460ff1615611163575065ffffffffffff81166000908152600f602090815260408083206001600160a01b03861684529091529020546105f2565b600061116e8361079e565b905060005b61117d60026119c1565b81101561131057600080806111936002856119cc565b9250925092506111a48282876119ee565b6111b057505050611308565b60005b601054816001600160601b0316101561130357836001600160a01b031663ce9b79306040518163ffffffff1660e01b8152600401602060405180830381865afa158015611204573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122891906127cb565b6001600160a01b031663e02f6937611272837f000000000000000000000000cb2fb374ff22ed8d1046a80601170c5e0b745ad76001600160a01b0316611bcf90919063ffffffff16565b604080516000815260208101918290526001600160e01b031960e085901b169091526112a691908d908b9060248101612812565b602060405180830381865afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e79190612854565b6112f19088612763565b96506112fc8161286d565b90506111b3565b505050505b600101611173565b505092915050565b6001818154811061132857600080fd5b906000526020600020906004020160009150905080600001805461134b9061256b565b80601f01602080910402602001604051908101604052809291908181526020018280546113779061256b565b80156113c45780601f10611399576101008083540402835291602001916113c4565b820191906000526020600020905b8154815290600101906020018083116113a757829003601f168201915b50505050600183015460028401546003909401549293909290915060ff1684565b6113ed611957565b6001600160a01b0381166114435760405162461bcd60e51b815260206004820152601860248201527f496e76616c6964206f70657261746f72206164647265737300000000000000006044820152606401610646565b6000611450600683611afe565b9050806000036114a25760405162461bcd60e51b815260206004820152601760248201527f4f70657261746f72206e6f7420726567697374657265640000000000000000006044820152606401610646565b6001600160a01b0382166000908152600c60205260408120805460ff191690556114cd600984611984565b91505065ffffffffffff8116158061152457506114e86119a1565b65ffffffffffff1661151a7f000000000000000000000000000000000000000000000000000000000001518083612725565b65ffffffffffff16115b15611542576040516377a2efc960e01b815260040160405180910390fd5b61154d6009846119ac565b506040516001600160a01b038416907f6f42117a557500c705ddf040a619d86f39101e6b74ac20d7b3e5943ba473fc7f90600090a2505050565b60007f00000000000000000000000000000000000000000000000000000000000000186115d47f0000000000000000000000000000000000000000000000000000000066f24a2084612744565b6105f29190612893565b6115e960063361193b565b6116415760405162461bcd60e51b815260206004820152602360248201527f43616c6c6572206973206e6f7420612072656769737465726564206f706572616044820152623a37b960e91b6064820152608401610646565b60015483106116845760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081d185cdac81251608a1b6044820152606401610646565b600060018481548110611699576116996128b8565b60009182526020822060049091020191506116b5600633611afe565b9050808260020154146117155760405162461bcd60e51b815260206004820152602260248201527f5461736b206e6f742061737369676e656420746f2074686973206f706572617460448201526137b960f11b6064820152608401610646565b600182015460405160009161173091859189916020016128ce565b6040516020818303038152906040528051906020012090506000611781827f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000908152601c91909152603c902090565b905060006117c787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508693925050611bf19050565b90506001600160a01b03811633146118155760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610646565b6001808981548110611829576118296128b8565b600091825260209182902060049190910201600301805460ff19169215159290921790915560405133815289917f18b7d306cc91d617b756cefb57e5c27c82a5dce9d470e537b52f823672212642910160405180910390a25050505050505050565b65ffffffffffff81166000908152600e602052604081205460ff16156118c6575065ffffffffffff166000908152600d602052604090205490565b6105f282611c1b565b60006118dc61050b6119a1565b905090565b60606118dc6002611d32565b6118f5611957565b610a14600282611b63565b611908611957565b6001600160a01b03811661193257604051631e4fbdf760e01b815260006004820152602401610646565b610a1481611b13565b6000611950836001600160a01b038416611d3f565b9392505050565b6000546001600160a01b031633146110fc5760405163118cdaa760e01b8152336004820152602401610646565b600080806119928585611afe565b95603087901c95509350505050565b60006118dc42611d4b565b6000611950836001600160a01b038416611d82565b60006105f282611d9f565b60008080806119db8686611daa565b9097909650603087901c95509350505050565b600065ffffffffffff841615801590611a1757508165ffffffffffff168465ffffffffffff1611155b8015611a43575065ffffffffffff83161580611a4357508165ffffffffffff168365ffffffffffff1610155b949350505050565b6000611a578383611afe565b905065ffffffffffff811615801590611a7a575065ffffffffffff603082901c16155b15611a9857604051637952fbad60e11b815260040160405180910390fd5b611aa06119a1565b65ffffffffffff169050611ab5838383611abb565b50505050565b6000611a43846001600160a01b03851684611dc6565b611add82826000611abb565b611afa5760405163f411c32760e01b815260040160405180910390fd5b5050565b6000611950836001600160a01b038416611de3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000611b6f8383611afe565b905065ffffffffffff81161580611b91575065ffffffffffff603082901c1615155b15611baf57604051633f54562b60e11b815260040160405180910390fd5b6030611bb96119a1565b65ffffffffffff16901b17611ab5838383611abb565b6001600160601b031660609190911b6bffffffffffffffffffffffff19161790565b600080600080611c018686611e2a565b925092509250611c118282611e77565b5090949350505050565b600080611c278361079e565b90507f0000000000000000000000000000000000000000000000000000000000015180611c526119a1565b611c5c9190612744565b65ffffffffffff168165ffffffffffff161015611c8c576040516312c7b10160e11b815260040160405180910390fd5b611c946119a1565b65ffffffffffff168165ffffffffffff161115611cc45760405163d5b25b6360e01b815260040160405180910390fd5b60005b611cd160096119c1565b811015611d2b5760008080611ce76009856119cc565b925092509250611cf88282876119ee565b611d0457505050611d23565b6000611d108487611111565b9050611d1c8188612763565b9650505050505b600101611cc7565b5050919050565b6060600061195083611f30565b60006119508383611f3b565b600065ffffffffffff821115611d7e576040516306dfcc6560e41b81526030600482015260248101839052604401610646565b5090565b600081815260028301602052604081208190556119508383611f53565b60006105f282611f5f565b6000808080611db98686611f69565b9097909650945050505050565b60008281526002840160205260408120829055611a438484611f94565b600081815260028301602052604081205480158015611e095750611e078484611d3f565b155b156119505760405163015ab34360e11b815260048101849052602401610646565b60008060008351604103611e645760208401516040850151606086015160001a611e5688828585611fa0565b955095509550505050611e70565b50508151600091506002905b9250925092565b6000826003811115611e8b57611e8b612798565b03611e94575050565b6001826003811115611ea857611ea8612798565b03611ec65760405163f645eedf60e01b815260040160405180910390fd5b6002826003811115611eda57611eda612798565b03611efb5760405163fce698f760e01b815260048101829052602401610646565b6003826003811115611f0f57611f0f612798565b03611afa576040516335e2f38360e21b815260048101829052602401610646565b60606105f28261206f565b60008181526001830160205260408120541515611950565b6000611950838361207c565b60006105f2825490565b60008080611f778585612176565b600081815260029690960160205260409095205494959350505050565b60006119508383612182565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115611fdb5750600091506003905082612065565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561202f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661205b57506000925060019150829050612065565b9250600091508190505b9450945094915050565b60606000611950836121d1565b600081815260018301602052604081205480156121655760006120a06001836126cb565b85549091506000906120b4906001906126cb565b90508082146121195760008660000182815481106120d4576120d46128b8565b90600052602060002001549050808760000184815481106120f7576120f76128b8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061212a5761212a612951565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f2565b60009150506105f2565b5092915050565b6000611950838361222d565b60008181526001830160205260408120546121c9575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f2565b5060006105f2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561222157602002820191906000526020600020905b81548152602001906001019080831161220d575b50505050509050919050565b6000826000018281548110612244576122446128b8565b9060005260206000200154905092915050565b6001600160a01b0381168114610a1457600080fd5b60006020828403121561227e57600080fd5b813561195081612257565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156122b157600080fd5b813567ffffffffffffffff808211156122c957600080fd5b818401915084601f8301126122dd57600080fd5b8135818111156122ef576122ef612289565b604051601f8201601f19908116603f0116810190838211818310171561231757612317612289565b8160405282815287602084870101111561233057600080fd5b826020860160208301376000928101602001929092525095945050505050565b65ffffffffffff81168114610a1457600080fd5b60006020828403121561237657600080fd5b813561195081612350565b60006020828403121561239357600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156123db5783516001600160a01b0316835292840192918401916001016123b6565b50909695505050505050565b600080604083850312156123fa57600080fd5b823561240581612257565b9150602083013561241581612350565b809150509250929050565b6000815180845260005b818110156124465760208185018101518683018201520161242a565b506000602082860101526020601f19601f83011685010191505092915050565b6080815260006124796080830187612420565b60208301959095525060408101929092521515606090910152919050565b6000806000604084860312156124ac57600080fd5b83359250602084013567ffffffffffffffff808211156124cb57600080fd5b818601915086601f8301126124df57600080fd5b8135818111156124ee57600080fd5b87602082850101111561250057600080fd5b6020830194508093505050509250925092565b6000806040838503121561252657600080fd5b823561253181612350565b9150602083013561241581612257565b634e487b7160e01b600052601260045260246000fd5b60008261256657612566612541565b500690565b600181811c9082168061257f57607f821691505b60208210810361259f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610889576000816000526020600020601f850160051c810160208610156125ce5750805b601f850160051c820191505b818110156125ed578281556001016125da565b505050505050565b815167ffffffffffffffff81111561260f5761260f612289565b6126238161261d845461256b565b846125a5565b602080601f83116001811461265857600084156126405750858301515b600019600386901b1c1916600185901b1785556125ed565b600085815260208120601f198616915b8281101561268757888601518255948401946001909101908401612668565b50858210156126a55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b818103818111156105f2576105f26126b5565b6060815260006126f16060830186612420565b60208301949094525060400152919050565b65ffffffffffff818116838216028082169190828114611310576113106126b5565b65ffffffffffff81811683821601908082111561216f5761216f6126b5565b65ffffffffffff82811682821603908082111561216f5761216f6126b5565b808201808211156105f2576105f26126b5565b60006020828403121561278857600080fd5b8151801515811461195057600080fd5b634e487b7160e01b600052602160045260246000fd5b6000602082840312156127c057600080fd5b815161195081612350565b6000602082840312156127dd57600080fd5b815161195081612257565b6000602082840312156127fa57600080fd5b815167ffffffffffffffff8116811461195057600080fd5b8481526001600160a01b038416602082015265ffffffffffff8316604082015260806060820181905260009061284a90830184612420565b9695505050505050565b60006020828403121561286657600080fd5b5051919050565b60006001600160601b03808316818103612889576128896126b5565b6001019392505050565b600065ffffffffffff808416806128ac576128ac612541565b92169190910492915050565b634e487b7160e01b600052603260045260246000fd5b60008085546128dc8161256b565b600182811680156128f4576001811461290957612938565b60ff1984168752821515830287019450612938565b8960005260208060002060005b8581101561292f5781548a820152908401908201612916565b50505082870194505b5050509481526020810193909352505060400192915050565b634e487b7160e01b600052603160045260246000fdfea264697066735822122060d14e1809bbd3f20c9c21b505974d74f63fbcd2108d50619bf2d12c1d92e5d664736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cb2fb374ff22ed8d1046a80601170c5e0b745ad7000000000000000000000000a02c55a6306c859517a064fb34d48dfb773a4a520000000000000000000000005035c15f3cb4364cf2cf35ca53e3d6fc45fc8899000000000000000000000000973ba45986ff71742129d23c4138bb3fad4f13a500000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000015180
-----Decoded View---------------
Arg [0] : _network (address): 0xcb2fb374FF22ED8d1046a80601170c5e0B745AD7
Arg [1] : _operatorRegistry (address): 0xa02C55a6306c859517A064fb34d48DFB773A4a52
Arg [2] : _vaultRegistry (address): 0x5035c15F3cb4364CF2cF35ca53E3d6FC45FC8899
Arg [3] : _operatorNetOptin (address): 0x973ba45986FF71742129d23C4138bb3fAd4f13A5
Arg [4] : _epochDuration (uint48): 24
Arg [5] : _slashingWindow (uint48): 86400
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000cb2fb374ff22ed8d1046a80601170c5e0b745ad7
Arg [1] : 000000000000000000000000a02c55a6306c859517a064fb34d48dfb773a4a52
Arg [2] : 0000000000000000000000005035c15f3cb4364cf2cf35ca53e3d6fc45fc8899
Arg [3] : 000000000000000000000000973ba45986ff71742129d23c4138bb3fad4f13a5
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000018
Arg [5] : 0000000000000000000000000000000000000000000000000000000000015180
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.