From 9a2c433ec7a50316ef66d44146f24b9dd41313f5 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 1 Oct 2025 12:14:45 -0400 Subject: [PATCH 1/3] feat: oracle weighted table calc --- .../BN254PriceWeightedTableCalculator.sol | 179 +++++++++++++++ test/mocks/ChainlinkAggregatorMock.sol | 41 ++++ ...N254PriceWeightedTableCalculatorUnit.t.sol | 214 ++++++++++++++++++ 3 files changed, 434 insertions(+) create mode 100644 src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol create mode 100644 test/mocks/ChainlinkAggregatorMock.sol create mode 100644 test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol diff --git a/src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol b/src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol new file mode 100644 index 00000000..b5406b21 --- /dev/null +++ b/src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.27; + +import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol"; +import {IAllocationManager} from + "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import {IKeyRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IKeyRegistrar.sol"; +import {IPermissionController} from + "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol"; +import {PermissionControllerMixin} from + "eigenlayer-contracts/src/contracts/mixins/PermissionControllerMixin.sol"; + +import "../BN254TableCalculatorBase.sol"; + +/// @notice Minimal Chainlink AggregatorV3 interface (inline to avoid an external dependency) +interface AggregatorV3Interface { + function decimals() external view returns (uint8); + function latestRoundData() + external + view + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); +} + +/** + * @title BN254PriceWeightedTableCalculator (UNAUDITED) + * @notice Calculates BN254 operator tables with weights derived from Chainlink oracle prices per strategy + * @dev For each operator, weight = sum_over_strategies( minSlashableStake(strategy) * price(strategy) ) + * Stake amounts and oracle prices are both normalized to 1e18 before multiplication to keep units consistent. + * Admins must configure price feeds and stake decimals per strategy (scoped by operator set) before use. + */ +contract BN254PriceWeightedTableCalculator is BN254TableCalculatorBase, PermissionControllerMixin { + /// @notice AllocationManager for stake queries + IAllocationManager public immutable allocationManager; + /// @notice Lookahead blocks used in slashable stake lookup + uint256 public immutable LOOKAHEAD_BLOCKS; + + /// @notice Strategy configuration scoped by operator set key + struct StrategyConfig { + AggregatorV3Interface priceFeed; // Chainlink price feed for the strategy's underlying + uint8 stakeDecimals; // Decimals of the strategy's stake unit (usually underlying token decimals) + bool feedSet; + bool stakeDecimalsSet; + } + + /// @dev operatorSetKey => strategy => config + mapping(bytes32 => mapping(IStrategy => StrategyConfig)) public strategyConfigs; + + /// @notice Emitted when price feeds are set for strategies + event StrategyPriceFeedsSet(OperatorSet indexed operatorSet, IStrategy[] strategies, address[] feeds); + /// @notice Emitted when stake decimals are set for strategies + event StrategyStakeDecimalsSet(OperatorSet indexed operatorSet, IStrategy[] strategies, uint8[] stakeDecimals); + + error ArrayLengthMismatch(); + + constructor( + IKeyRegistrar _keyRegistrar, + IAllocationManager _allocationManager, + IPermissionController _permissionController, + uint256 _LOOKAHEAD_BLOCKS + ) BN254TableCalculatorBase(_keyRegistrar) PermissionControllerMixin(_permissionController) { + allocationManager = _allocationManager; + LOOKAHEAD_BLOCKS = _LOOKAHEAD_BLOCKS; + } + + /** + * @notice Set Chainlink price feeds per strategy for a specific operator set + * @dev Restricted to the AVS of the operator set via PermissionController + */ + function setStrategyPriceFeeds( + OperatorSet calldata operatorSet, + IStrategy[] calldata strategies, + address[] calldata feeds + ) external checkCanCall(operatorSet.avs) { + if (strategies.length != feeds.length) revert ArrayLengthMismatch(); + bytes32 key = operatorSet.key(); + for (uint256 i = 0; i < strategies.length; i++) { + strategyConfigs[key][strategies[i]].priceFeed = AggregatorV3Interface(feeds[i]); + strategyConfigs[key][strategies[i]].feedSet = feeds[i] != address(0); + } + emit StrategyPriceFeedsSet(operatorSet, strategies, feeds); + } + + /** + * @notice Set stake decimals per strategy for a specific operator set + * @dev Restricted to the AVS of the operator set via PermissionController + */ + function setStrategyStakeDecimals( + OperatorSet calldata operatorSet, + IStrategy[] calldata strategies, + uint8[] calldata stakeDecimals + ) external checkCanCall(operatorSet.avs) { + if (strategies.length != stakeDecimals.length) revert ArrayLengthMismatch(); + bytes32 key = operatorSet.key(); + for (uint256 i = 0; i < strategies.length; i++) { + strategyConfigs[key][strategies[i]].stakeDecimals = stakeDecimals[i]; + strategyConfigs[key][strategies[i]].stakeDecimalsSet = true; + } + emit StrategyStakeDecimalsSet(operatorSet, strategies, stakeDecimals); + } + + /** + * @notice Weight calculation using Chainlink prices + * @dev Only strategies with both a configured feed and stake decimals contribute to weights + */ + function _getOperatorWeights( + OperatorSet calldata operatorSet + ) internal view override returns (address[] memory operators, uint256[][] memory weights) { + address[] memory registeredOperators = allocationManager.getMembers(operatorSet); + IStrategy[] memory strategies = allocationManager.getStrategiesInOperatorSet(operatorSet); + + uint256[][] memory minSlashableStake = allocationManager.getMinimumSlashableStake({ + operatorSet: operatorSet, + operators: registeredOperators, + strategies: strategies, + futureBlock: uint32(block.number + LOOKAHEAD_BLOCKS) + }); + + bytes32 key = operatorSet.key(); + + operators = new address[](registeredOperators.length); + weights = new uint256[][](registeredOperators.length); + uint256 operatorCount = 0; + + for (uint256 i = 0; i < registeredOperators.length; ++i) { + uint256 totalWeight; + for (uint256 stratIndex = 0; stratIndex < strategies.length; ++stratIndex) { + uint256 stakeAmount = minSlashableStake[i][stratIndex]; + if (stakeAmount == 0) continue; + + StrategyConfig memory cfg = strategyConfigs[key][strategies[stratIndex]]; + if (!cfg.feedSet || !cfg.stakeDecimalsSet) continue; + + AggregatorV3Interface feed = cfg.priceFeed; + if (address(feed) == address(0)) continue; + + (, int256 price, , , ) = feed.latestRoundData(); + if (price <= 0) continue; + + uint8 priceDecimals = feed.decimals(); + + // Normalize stake to 1e18: stakeAmount * 10^(18 - stakeDecimals) + uint256 stakeScaled = _scaleTo1e18(stakeAmount, cfg.stakeDecimals); + // Normalize price to 1e18 + uint256 priceScaled = _scaleTo1e18(uint256(price), priceDecimals); + + // weight += (stakeScaled * priceScaled) / 1e18 + totalWeight += (stakeScaled * priceScaled) / 1e18; + } + + if (totalWeight > 0) { + weights[operatorCount] = new uint256[](1); + weights[operatorCount][0] = totalWeight; + operators[operatorCount] = registeredOperators[i]; + operatorCount++; + } + } + + assembly { + mstore(operators, operatorCount) + mstore(weights, operatorCount) + } + + return (operators, weights); + } + + function _scaleTo1e18(uint256 amount, uint8 decimals_) private pure returns (uint256) { + if (decimals_ == 18) return amount; + if (decimals_ < 18) { + unchecked { + return amount * (10 ** (18 - decimals_)); + } + } + // decimals_ > 18 + return amount / (10 ** (decimals_ - 18)); + } +} + + diff --git a/test/mocks/ChainlinkAggregatorMock.sol b/test/mocks/ChainlinkAggregatorMock.sol new file mode 100644 index 00000000..b12c1223 --- /dev/null +++ b/test/mocks/ChainlinkAggregatorMock.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.27; + +interface IAggregatorV3MockLike { + function decimals() external view returns (uint8); + function latestRoundData() + external + view + returns (uint80, int256, uint256, uint256, uint80); +} + +contract ChainlinkAggregatorMock is IAggregatorV3MockLike { + uint8 public immutable overrideDecimals; + int256 public currentAnswer; + uint256 public currentUpdatedAt; + + constructor(uint8 _decimals, int256 _answer) { + overrideDecimals = _decimals; + currentAnswer = _answer; + currentUpdatedAt = block.timestamp; + } + + function setAnswer(int256 _answer) external { + currentAnswer = _answer; + currentUpdatedAt = block.timestamp; + } + + function decimals() external view returns (uint8) { + return overrideDecimals; + } + + function latestRoundData() + external + view + returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80) + { + return (0, currentAnswer, 0, currentUpdatedAt, 0); + } +} + + diff --git a/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol b/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol new file mode 100644 index 00000000..049396b8 --- /dev/null +++ b/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.27; + +import {IAllocationManager} from + "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol"; +import {IKeyRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IKeyRegistrar.sol"; +import {IPermissionController} from + "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol"; +import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol"; +import { + OperatorSet, + OperatorSetLib +} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol"; + +import {BN254TableCalculatorBase} from + "../../../src/middlewareV2/tableCalculator/BN254TableCalculatorBase.sol"; +import {BN254PriceWeightedTableCalculator} from + "../../../src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol"; +import {MockEigenLayerDeployer} from "./MockDeployer.sol"; +import {ChainlinkAggregatorMock} from "test/mocks/ChainlinkAggregatorMock.sol"; + +contract BN254PriceWeightedTableCalculatorHarness is BN254PriceWeightedTableCalculator { + constructor( + IKeyRegistrar _keyRegistrar, + IAllocationManager _allocationManager, + IPermissionController _permissionController, + uint256 _LOOKAHEAD_BLOCKS + ) + BN254PriceWeightedTableCalculator( + _keyRegistrar, _allocationManager, _permissionController, _LOOKAHEAD_BLOCKS + ) + {} + + function exposed_getOperatorWeights( + OperatorSet calldata operatorSet + ) external view returns (address[] memory operators, uint256[][] memory weights) { + return _getOperatorWeights(operatorSet); + } +} + +contract BN254PriceWeightedTableCalculatorUnitTests is MockEigenLayerDeployer { + using OperatorSetLib for OperatorSet; + + BN254PriceWeightedTableCalculatorHarness public calculator; + OperatorSet public operatorSet; + + // Simple strategy identifiers + IStrategy public strategy1 = IStrategy(address(0x100)); + IStrategy public strategy2 = IStrategy(address(0x200)); + + // Actors + address public avs1 = address(0x1); + address public operator1 = address(0x3); + address public operator2 = address(0x4); + + uint256 public constant TEST_LOOKAHEAD_BLOCKS = 100; + + function setUp() public { + _deployMockEigenLayer(); + calculator = new BN254PriceWeightedTableCalculatorHarness( + IKeyRegistrar(address(keyRegistrarMock)), + IAllocationManager(address(allocationManagerMock)), + IPermissionController(address(permissionController)), + TEST_LOOKAHEAD_BLOCKS + ); + operatorSet = OperatorSet({avs: avs1, id: 7}); + } + + function _setupOperatorSet( + OperatorSet memory opSet, + address[] memory operators, + IStrategy[] memory strategies, + uint256[][] memory minSlashableStake + ) internal { + allocationManagerMock.setMembersInOperatorSet(opSet, operators); + allocationManagerMock.setStrategiesInOperatorSet(opSet, strategies); + allocationManagerMock.setMinimumSlashableStake(opSet, operators, strategies, minSlashableStake); + } + + function test_getOperatorWeights_priceWeighted_basic() public { + // two operators, two strategies + address[] memory operators = new address[](2); + operators[0] = operator1; + operators[1] = operator2; + + IStrategy[] memory strategies = new IStrategy[](2); + strategies[0] = strategy1; // token with 18 decimals + strategies[1] = strategy2; // token with 6 decimals + + uint256[][] memory stakes = new uint256[][](2); + stakes[0] = new uint256[](2); + stakes[1] = new uint256[](2); + + // operator1: 10 units on s1, 2,000,000 units on s2 (to simulate 6 decimals scale) + stakes[0][0] = 10 ether; // assume already in 1e18 for simplicity + stakes[0][1] = 2_000_000; // raw amount with 6 decimals + + // operator2: 5 units on s1, 3,000,000 units on s2 + stakes[1][0] = 5 ether; + stakes[1][1] = 3_000_000; + + _setupOperatorSet(operatorSet, operators, strategies, stakes); + + // Configure feeds and decimals + // price1 = 2e8 with 8 decimals => 2.0 -> scaled to 1e18 becomes 2e18 + ChainlinkAggregatorMock feed1 = new ChainlinkAggregatorMock(8, 200_000_000); + // price2 = 3e8 with 8 decimals => 3.0 -> scaled to 1e18 becomes 3e18 + ChainlinkAggregatorMock feed2 = new ChainlinkAggregatorMock(8, 300_000_000); + + IStrategy[] memory feedStrats = new IStrategy[](2); + feedStrats[0] = strategy1; + feedStrats[1] = strategy2; + address[] memory feeds = new address[](2); + feeds[0] = address(feed1); + feeds[1] = address(feed2); + + vm.prank(avs1); + calculator.setStrategyPriceFeeds(operatorSet, feedStrats, feeds); + + // set stake decimals: s1=18, s2=6 + IStrategy[] memory decStrats = new IStrategy[](2); + decStrats[0] = strategy1; + decStrats[1] = strategy2; + uint8[] memory decs = new uint8[](2); + decs[0] = 18; + decs[1] = 6; + vm.prank(avs1); + calculator.setStrategyStakeDecimals(operatorSet, decStrats, decs); + + // Compute + (address[] memory resultOperators, uint256[][] memory resultWeights) = + calculator.exposed_getOperatorWeights(operatorSet); + + assertEq(resultOperators.length, 2); + assertEq(resultOperators[0], operator1); + assertEq(resultOperators[1], operator2); + + // Expected: + // op1: s1 -> 10e18 * 2e18 / 1e18 = 20e18 + // s2 -> (2_000_000 scaled from 6 to 18 => 2_000_000 * 1e12 = 2e18) * 3e18 / 1e18 = 6e18 + // total = 26e18 + assertEq(resultWeights[0][0], 26 ether); + + // op2: s1 -> 5e18 * 2e18 / 1e18 = 10e18 + // s2 -> (3_000_000 -> 3e18) * 3e18 / 1e18 = 9e18 + // total = 19e18 + assertEq(resultWeights[1][0], 19 ether); + } + + function test_getOperatorWeights_skipsUnsetFeedsOrDecimals() public { + address[] memory operators = new address[](1); + operators[0] = operator1; + + IStrategy[] memory strategies = new IStrategy[](1); + strategies[0] = strategy1; + + uint256[][] memory stakes = new uint256[][](1); + stakes[0] = new uint256[](1); + stakes[0][0] = 100 ether; + + _setupOperatorSet(operatorSet, operators, strategies, stakes); + + // Only set price feed, not stake decimals -> skipped + ChainlinkAggregatorMock feed1 = new ChainlinkAggregatorMock(8, 200_000_000); + IStrategy[] memory feedStrats = new IStrategy[](1); + feedStrats[0] = strategy1; + address[] memory feeds = new address[](1); + feeds[0] = address(feed1); + vm.prank(avs1); + calculator.setStrategyPriceFeeds(operatorSet, feedStrats, feeds); + + (address[] memory resultOperators, uint256[][] memory resultWeights) = + calculator.exposed_getOperatorWeights(operatorSet); + // Should be skipped due to missing stake decimals -> zero operators + assertEq(resultOperators.length, 0); + assertEq(resultWeights.length, 0); + } + + function test_getOperatorWeights_skipsNonPositivePrice() public { + address[] memory operators = new address[](1); + operators[0] = operator1; + + IStrategy[] memory strategies = new IStrategy[](1); + strategies[0] = strategy1; + + uint256[][] memory stakes = new uint256[][](1); + stakes[0] = new uint256[](1); + stakes[0][0] = 100 ether; + _setupOperatorSet(operatorSet, operators, strategies, stakes); + + // Set decimals but zero price + IStrategy[] memory decStrats = new IStrategy[](1); + decStrats[0] = strategy1; + uint8[] memory decs = new uint8[](1); + decs[0] = 18; + vm.prank(avs1); + calculator.setStrategyStakeDecimals(operatorSet, decStrats, decs); + + ChainlinkAggregatorMock feed = new ChainlinkAggregatorMock(8, 0); + IStrategy[] memory feedStrats = new IStrategy[](1); + feedStrats[0] = strategy1; + address[] memory feeds = new address[](1); + feeds[0] = address(feed); + vm.prank(avs1); + calculator.setStrategyPriceFeeds(operatorSet, feedStrats, feeds); + + (address[] memory resultOperators, uint256[][] memory resultWeights) = + calculator.exposed_getOperatorWeights(operatorSet); + assertEq(resultOperators.length, 0); + assertEq(resultWeights.length, 0); + } +} + + From 766fd83acf9ab4b22796356abd9493075483525d Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 1 Oct 2025 12:16:00 -0400 Subject: [PATCH 2/3] chore: forge fmt --- .../BN254PriceWeightedTableCalculator.sol | 25 +++++++++++++------ test/mocks/ChainlinkAggregatorMock.sol | 11 +++----- ...N254PriceWeightedTableCalculatorUnit.t.sol | 21 +++++++++------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol b/src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol index b5406b21..703aad94 100644 --- a/src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol +++ b/src/middlewareV2/tableCalculator/unaudited/BN254PriceWeightedTableCalculator.sol @@ -19,7 +19,13 @@ interface AggregatorV3Interface { function latestRoundData() external view - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); + returns ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ); } /** @@ -29,7 +35,10 @@ interface AggregatorV3Interface { * Stake amounts and oracle prices are both normalized to 1e18 before multiplication to keep units consistent. * Admins must configure price feeds and stake decimals per strategy (scoped by operator set) before use. */ -contract BN254PriceWeightedTableCalculator is BN254TableCalculatorBase, PermissionControllerMixin { +contract BN254PriceWeightedTableCalculator is + BN254TableCalculatorBase, + PermissionControllerMixin +{ /// @notice AllocationManager for stake queries IAllocationManager public immutable allocationManager; /// @notice Lookahead blocks used in slashable stake lookup @@ -47,9 +56,13 @@ contract BN254PriceWeightedTableCalculator is BN254TableCalculatorBase, Permissi mapping(bytes32 => mapping(IStrategy => StrategyConfig)) public strategyConfigs; /// @notice Emitted when price feeds are set for strategies - event StrategyPriceFeedsSet(OperatorSet indexed operatorSet, IStrategy[] strategies, address[] feeds); + event StrategyPriceFeedsSet( + OperatorSet indexed operatorSet, IStrategy[] strategies, address[] feeds + ); /// @notice Emitted when stake decimals are set for strategies - event StrategyStakeDecimalsSet(OperatorSet indexed operatorSet, IStrategy[] strategies, uint8[] stakeDecimals); + event StrategyStakeDecimalsSet( + OperatorSet indexed operatorSet, IStrategy[] strategies, uint8[] stakeDecimals + ); error ArrayLengthMismatch(); @@ -134,7 +147,7 @@ contract BN254PriceWeightedTableCalculator is BN254TableCalculatorBase, Permissi AggregatorV3Interface feed = cfg.priceFeed; if (address(feed) == address(0)) continue; - (, int256 price, , , ) = feed.latestRoundData(); + (, int256 price,,,) = feed.latestRoundData(); if (price <= 0) continue; uint8 priceDecimals = feed.decimals(); @@ -175,5 +188,3 @@ contract BN254PriceWeightedTableCalculator is BN254TableCalculatorBase, Permissi return amount / (10 ** (decimals_ - 18)); } } - - diff --git a/test/mocks/ChainlinkAggregatorMock.sol b/test/mocks/ChainlinkAggregatorMock.sol index b12c1223..a4d559e9 100644 --- a/test/mocks/ChainlinkAggregatorMock.sol +++ b/test/mocks/ChainlinkAggregatorMock.sol @@ -3,10 +3,7 @@ pragma solidity ^0.8.27; interface IAggregatorV3MockLike { function decimals() external view returns (uint8); - function latestRoundData() - external - view - returns (uint80, int256, uint256, uint256, uint80); + function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80); } contract ChainlinkAggregatorMock is IAggregatorV3MockLike { @@ -20,7 +17,9 @@ contract ChainlinkAggregatorMock is IAggregatorV3MockLike { currentUpdatedAt = block.timestamp; } - function setAnswer(int256 _answer) external { + function setAnswer( + int256 _answer + ) external { currentAnswer = _answer; currentUpdatedAt = block.timestamp; } @@ -37,5 +36,3 @@ contract ChainlinkAggregatorMock is IAggregatorV3MockLike { return (0, currentAnswer, 0, currentUpdatedAt, 0); } } - - diff --git a/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol b/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol index 049396b8..f373e58c 100644 --- a/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol +++ b/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol @@ -27,7 +27,10 @@ contract BN254PriceWeightedTableCalculatorHarness is BN254PriceWeightedTableCalc uint256 _LOOKAHEAD_BLOCKS ) BN254PriceWeightedTableCalculator( - _keyRegistrar, _allocationManager, _permissionController, _LOOKAHEAD_BLOCKS + _keyRegistrar, + _allocationManager, + _permissionController, + _LOOKAHEAD_BLOCKS ) {} @@ -74,7 +77,9 @@ contract BN254PriceWeightedTableCalculatorUnitTests is MockEigenLayerDeployer { ) internal { allocationManagerMock.setMembersInOperatorSet(opSet, operators); allocationManagerMock.setStrategiesInOperatorSet(opSet, strategies); - allocationManagerMock.setMinimumSlashableStake(opSet, operators, strategies, minSlashableStake); + allocationManagerMock.setMinimumSlashableStake( + opSet, operators, strategies, minSlashableStake + ); } function test_getOperatorWeights_priceWeighted_basic() public { @@ -93,19 +98,19 @@ contract BN254PriceWeightedTableCalculatorUnitTests is MockEigenLayerDeployer { // operator1: 10 units on s1, 2,000,000 units on s2 (to simulate 6 decimals scale) stakes[0][0] = 10 ether; // assume already in 1e18 for simplicity - stakes[0][1] = 2_000_000; // raw amount with 6 decimals + stakes[0][1] = 2000000; // raw amount with 6 decimals // operator2: 5 units on s1, 3,000,000 units on s2 stakes[1][0] = 5 ether; - stakes[1][1] = 3_000_000; + stakes[1][1] = 3000000; _setupOperatorSet(operatorSet, operators, strategies, stakes); // Configure feeds and decimals // price1 = 2e8 with 8 decimals => 2.0 -> scaled to 1e18 becomes 2e18 - ChainlinkAggregatorMock feed1 = new ChainlinkAggregatorMock(8, 200_000_000); + ChainlinkAggregatorMock feed1 = new ChainlinkAggregatorMock(8, 200000000); // price2 = 3e8 with 8 decimals => 3.0 -> scaled to 1e18 becomes 3e18 - ChainlinkAggregatorMock feed2 = new ChainlinkAggregatorMock(8, 300_000_000); + ChainlinkAggregatorMock feed2 = new ChainlinkAggregatorMock(8, 300000000); IStrategy[] memory feedStrats = new IStrategy[](2); feedStrats[0] = strategy1; @@ -161,7 +166,7 @@ contract BN254PriceWeightedTableCalculatorUnitTests is MockEigenLayerDeployer { _setupOperatorSet(operatorSet, operators, strategies, stakes); // Only set price feed, not stake decimals -> skipped - ChainlinkAggregatorMock feed1 = new ChainlinkAggregatorMock(8, 200_000_000); + ChainlinkAggregatorMock feed1 = new ChainlinkAggregatorMock(8, 200000000); IStrategy[] memory feedStrats = new IStrategy[](1); feedStrats[0] = strategy1; address[] memory feeds = new address[](1); @@ -210,5 +215,3 @@ contract BN254PriceWeightedTableCalculatorUnitTests is MockEigenLayerDeployer { assertEq(resultWeights.length, 0); } } - - From ee89aa089ef6bcfec6956106d13c166ec4251fb4 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 7 Oct 2025 07:59:08 -0400 Subject: [PATCH 3/3] chore: fmt: --- test/mocks/ChainlinkAggregatorMock.sol | 1 + .../middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol | 1 + 2 files changed, 2 insertions(+) diff --git a/test/mocks/ChainlinkAggregatorMock.sol b/test/mocks/ChainlinkAggregatorMock.sol index a4d559e9..7f7b8eaf 100644 --- a/test/mocks/ChainlinkAggregatorMock.sol +++ b/test/mocks/ChainlinkAggregatorMock.sol @@ -36,3 +36,4 @@ contract ChainlinkAggregatorMock is IAggregatorV3MockLike { return (0, currentAnswer, 0, currentUpdatedAt, 0); } } + diff --git a/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol b/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol index f373e58c..df5ee52c 100644 --- a/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol +++ b/test/unit/middlewareV2/BN254PriceWeightedTableCalculatorUnit.t.sol @@ -215,3 +215,4 @@ contract BN254PriceWeightedTableCalculatorUnitTests is MockEigenLayerDeployer { assertEq(resultWeights.length, 0); } } +