Skip to content

Commit

Permalink
chore: map with time v3
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Dec 16, 2024
1 parent 37c0bc3 commit 2b0ca89
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 21 deletions.
28 changes: 14 additions & 14 deletions bolt-contracts/src/contracts/BoltManagerV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {Time} from "@openzeppelin/contracts/utils/types/Time.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import {OperatorMapWithTimeV2} from "../lib/OperatorMapWithTimeV2.sol";
import {EnumerableMapV2} from "../lib/EnumerableMapV2.sol";
import {OperatorMapWithTimeV3} from "../lib/OperatorMapWithTimeV3.sol";
import {EnumerableMapV3} from "../lib/EnumerableMapV3.sol";
import {IBoltParametersV1} from "../interfaces/IBoltParametersV1.sol";
import {IBoltMiddlewareV1} from "../interfaces/IBoltMiddlewareV1.sol";
import {IBoltValidatorsV2} from "../interfaces/IBoltValidatorsV2.sol";
Expand All @@ -24,11 +24,11 @@ import {IBoltManagerV3} from "../interfaces/IBoltManagerV3.sol";
/// You can also validate manually with forge: forge inspect <contract> storage-layout --pretty
contract BoltManagerV3 is IBoltManagerV3, OwnableUpgradeable, UUPSUpgradeable {
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableMapV2 for EnumerableMapV2.OperatorMap;
using OperatorMapWithTimeV2 for EnumerableMapV2.OperatorMap;
using EnumerableMapV3 for EnumerableMapV3.OperatorMap;
using OperatorMapWithTimeV3 for EnumerableMapV3.OperatorMap;

// ========= STORAGE =========

/// @notice Start timestamp of the first epoch.
uint48 public START_TIMESTAMP;

Expand All @@ -40,7 +40,7 @@ contract BoltManagerV3 is IBoltManagerV3, OwnableUpgradeable, UUPSUpgradeable {
IBoltValidatorsV2 public validators;

/// @notice Set of operator addresses that have opted in to Bolt Protocol.
EnumerableMapV2.OperatorMap private operators;
EnumerableMapV3.OperatorMap private operators;

/// @notice Set of restaking protocols supported. Each address corresponds to the
/// associated Bolt Middleware contract.
Expand Down Expand Up @@ -170,16 +170,16 @@ contract BoltManagerV3 is IBoltManagerV3, OwnableUpgradeable, UUPSUpgradeable {
/// @return operatorData The operator data.
function getOperatorData(
address operator
) public view returns (EnumerableMapV2.Operator memory operatorData) {
) public view returns (EnumerableMapV3.Operator memory operatorData) {
return operators.get(operator);
}

/// @notice Get the data of all registered operators.
/// @return operatorData An array of operator data.
function getAllOperatorsData() public view returns (EnumerableMapV2.Operator[] memory operatorData) {
operatorData = new EnumerableMapV2.Operator[](operators.length());
function getAllOperatorsData() public view returns (EnumerableMapV3.Operator[] memory operatorData) {
operatorData = new EnumerableMapV3.Operator[](operators.length());
for (uint256 i = 0; i < operators.length(); ++i) {
(address operator, EnumerableMapV2.Operator memory data) = operators.at(i);
(address operator, EnumerableMapV3.Operator memory data) = operators.at(i);
operatorData[i] = data;
}
}
Expand Down Expand Up @@ -210,7 +210,7 @@ contract BoltManagerV3 is IBoltManagerV3, OwnableUpgradeable, UUPSUpgradeable {
// NOTE: this will revert when the proposer does not exist.
IBoltValidatorsV2.ValidatorInfo memory validator = validators.getValidatorByPubkeyHash(pubkeyHash);

EnumerableMapV2.Operator memory operatorData = operators.get(validator.authorizedOperator);
EnumerableMapV3.Operator memory operatorData = operators.get(validator.authorizedOperator);

status.pubkeyHash = pubkeyHash;
status.operator = validator.authorizedOperator;
Expand Down Expand Up @@ -245,7 +245,7 @@ contract BoltManagerV3 is IBoltManagerV3, OwnableUpgradeable, UUPSUpgradeable {
/// @param collateral The address of the collateral asset to get the stake for.
/// @return amount The amount staked by the operator for the given collateral asset.
function getOperatorStake(address operator, address collateral) public view returns (uint256) {
EnumerableMapV2.Operator memory operatorData = operators.get(operator);
EnumerableMapV3.Operator memory operatorData = operators.get(operator);

return IBoltMiddlewareV1(operatorData.middleware).getOperatorStake(operator, collateral);
}
Expand All @@ -258,7 +258,7 @@ contract BoltManagerV3 is IBoltManagerV3, OwnableUpgradeable, UUPSUpgradeable {
) public view returns (uint256 amount) {
// Loop over all of the operators, get their middleware, and retrieve their staked amount.
for (uint256 i = 0; i < operators.length(); ++i) {
(address operator, EnumerableMapV2.Operator memory operatorData) = operators.at(i);
(address operator, EnumerableMapV3.Operator memory operatorData) = operators.at(i);
amount += IBoltMiddlewareV1(operatorData.middleware).getOperatorStake(operator, collateral);
}

Expand All @@ -276,7 +276,7 @@ contract BoltManagerV3 is IBoltManagerV3, OwnableUpgradeable, UUPSUpgradeable {
}

// Create an already enabled operator
EnumerableMapV2.Operator memory operator = EnumerableMapV2.Operator(rpc, msg.sender, Time.timestamp());
EnumerableMapV3.Operator memory operator = EnumerableMapV3.Operator(rpc, msg.sender, Time.timestamp());

operators.set(operatorAddr, operator);
}
Expand Down
8 changes: 3 additions & 5 deletions bolt-contracts/src/interfaces/IBoltManagerv3.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {EnumerableMapV2} from "../lib/EnumerableMapV2.sol";
import {EnumerableMapV3} from "../lib/EnumerableMapV3.sol";

interface IBoltManagerV3 {
error InvalidQuery();
error OperatorAlreadyRegistered();
error OperatorNotRegistered();
error UnauthorizedMiddleware();
// TODO: remove in future upgrade (unused)
error InactiveOperator();

/// @notice Proposer status info.
struct ProposerStatus {
Expand Down Expand Up @@ -47,9 +45,9 @@ interface IBoltManagerV3 {

function getOperatorData(
address operator
) external view returns (EnumerableMapV2.Operator memory operatorData);
) external view returns (EnumerableMapV3.Operator memory operatorData);

function getAllOperatorsData() external view returns (EnumerableMapV2.Operator[] memory operatorData);
function getAllOperatorsData() external view returns (EnumerableMapV3.Operator[] memory operatorData);

function getProposerStatus(
bytes20 pubkeyHash
Expand Down
4 changes: 2 additions & 2 deletions bolt-contracts/src/lib/EnumerableMapV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity 0.8.25;

import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

library EnumerableMapV2 {
library EnumerableMapV3 {
using EnumerableSet for EnumerableSet.Bytes32Set;

error KeyNotFound(address key);
Expand Down Expand Up @@ -52,7 +52,7 @@ library EnumerableMapV2 {

function get(OperatorMap storage self, address key) internal view returns (Operator memory) {
if (!contains(self, key)) {
revert KeyNotFound();
revert KeyNotFound(key);
}

return self._values[bytes32(uint256(uint160(key)))];
Expand Down
70 changes: 70 additions & 0 deletions bolt-contracts/src/lib/OperatorMapWithTimeV3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// 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 {EnumerableMapV3} from "./EnumerableMapV3.sol";

library OperatorMapWithTimeV3 {
using EnumerableMapV3 for EnumerableMapV3.OperatorMap;

error AlreadyAdded();
error NotEnabled();
error AlreadyEnabled();

uint256 private constant ENABLED_TIME_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 private constant DISABLED_TIME_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFF << 48;

function add(EnumerableMapV3.OperatorMap storage self, address addr) internal {
if (!self.set(addr, EnumerableMapV3.Operator("", address(0), 0))) {
revert AlreadyAdded();
}
}

function disable(EnumerableMapV3.OperatorMap storage self, address addr) internal {
EnumerableMapV3.Operator memory operator = self.get(addr);
uint256 value = operator.timestamp;

if (uint48(value) == 0 || uint48(value >> 48) != 0) {
revert NotEnabled();
}

value |= uint256(Time.timestamp()) << 48;
operator.timestamp = value;
self.set(addr, operator);
}

function enable(EnumerableMapV3.OperatorMap storage self, address addr) internal {
EnumerableMapV3.Operator memory operator = self.get(addr);
uint256 value = operator.timestamp;

if (uint48(value) != 0 && uint48(value >> 48) == 0) {
revert AlreadyEnabled();
}

value = uint256(Time.timestamp());
operator.timestamp = value;
self.set(addr, operator);
}

function atWithTimes(
EnumerableMapV3.OperatorMap storage self,
uint256 idx
) internal view returns (address key, uint48 enabledTime, uint48 disabledTime) {
EnumerableMapV3.Operator memory value;
(key, value) = self.at(idx);
uint256 timestamp = value.timestamp;
enabledTime = uint48(timestamp);
disabledTime = uint48(timestamp >> 48);
}

function getTimes(
EnumerableMapV3.OperatorMap storage self,
address addr
) internal view returns (uint48 enabledTime, uint48 disabledTime) {
EnumerableMapV3.Operator memory value = self.get(addr);
enabledTime = uint48(value.timestamp);
disabledTime = uint48(value.timestamp >> 48);
}
}

0 comments on commit 2b0ca89

Please sign in to comment.