From 5b09e483053728867b2b3b3ecc953253d761a3df Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 16:25:12 +0400 Subject: [PATCH 01/14] fix: statemind - SimplePosMiddleware incorrect slash amount calculation --- src/examples/simple-pos-network/SimplePosMiddleware.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/simple-pos-network/SimplePosMiddleware.sol b/src/examples/simple-pos-network/SimplePosMiddleware.sol index f8da19b..6ec96f1 100644 --- a/src/examples/simple-pos-network/SimplePosMiddleware.sol +++ b/src/examples/simple-pos-network/SimplePosMiddleware.sol @@ -147,7 +147,7 @@ contract SimplePosMiddleware is params.vaults = _activeVaultsAt(params.epochStart, params.operator); params.subnetworks = _activeSubnetworksAt(params.epochStart); - params.totalPower = _getOperatorPower(params.operator, params.vaults, params.subnetworks); + params.totalPower = _getOperatorPowerAt(params.epochStart, params.operator, params.vaults, params.subnetworks); uint256 vaultsLength = params.vaults.length; uint256 subnetworksLength = params.subnetworks.length; From f7a679b8f918316fa1dfe3851499844b5a4145e7 Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 16:39:44 +0400 Subject: [PATCH 02/14] fix: statemind - Slashing in the future --- src/managers/VaultManager.sol | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/managers/VaultManager.sol b/src/managers/VaultManager.sol index 615a75f..0cf365f 100644 --- a/src/managers/VaultManager.sol +++ b/src/managers/VaultManager.sol @@ -43,6 +43,7 @@ abstract contract VaultManager is NetworkStorage, SlashingWindowStorage, Capture error NoSlasher(); error TooOldTimestampSlash(); error NotOperatorSpecificVault(); + error FutureTimestampSlash(); /// @custom:storage-location erc7201:symbiotic.storage.VaultManager struct VaultManagerStorage { @@ -644,6 +645,11 @@ abstract contract VaultManager is NetworkStorage, SlashingWindowStorage, Capture bytes memory hints ) internal returns (uint256 response) { VaultManagerStorage storage $ = _getVaultManagerStorage(); + + if (timestamp > _now()) { + revert FutureTimestampSlash(); + } + if (!($._sharedVaults.contains(vault) || $._operatorVaults[operator].contains(vault))) { revert NotOperatorVault(); } From b4b687d2cac4b58600d803d993083a47818d3567 Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 16:46:31 +0400 Subject: [PATCH 03/14] fix: statemind - Unable to unregister Operator and Operator Vault after forcePause --- .../operators/ForcePauseSelfRegisterOperators.sol | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/extensions/operators/ForcePauseSelfRegisterOperators.sol b/src/extensions/operators/ForcePauseSelfRegisterOperators.sol index d8c474a..ed5f3f5 100644 --- a/src/extensions/operators/ForcePauseSelfRegisterOperators.sol +++ b/src/extensions/operators/ForcePauseSelfRegisterOperators.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.25; import {SelfRegisterOperators} from "./SelfRegisterOperators.sol"; import {IForcePauseSelfRegisterOperators} from "../../interfaces/extensions/operators/IForcePauseSelfRegisterOperators.sol"; +import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; /** * @title ForcePauseSelfRegisterOperators @@ -11,6 +12,8 @@ import {IForcePauseSelfRegisterOperators} from * @dev Implements force pause functionality and prevents unpausing of force-paused operators */ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IForcePauseSelfRegisterOperators { + using EnumerableMap for EnumerableMap.AddressToAddressMap; + uint64 public constant ForcePauseSelfRegisterOperators_VERSION = 1; struct ForcePauseSelfRegisterOperatorsStorage { @@ -51,6 +54,9 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor ) external checkAccess { ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); $.forcePaused[operator] = false; + if (!_isOperatorRegistered(operator)) { + return; + } _beforeUnpauseOperator(operator); _unpauseOperator(operator); } @@ -83,6 +89,10 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor function forceUnpauseOperatorVault(address operator, address vault) external checkAccess { ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); $.forcePausedVault[operator][vault] = false; + VaultManagerStorage storage s = _getVaultManagerStorage(); + if (!s._vaultOperator.contains(vault)) { + return; + } _beforeUnpauseOperatorVault(operator, vault); _unpauseOperatorVault(operator, vault); } From 05e4b52214d5c9b92b356d2c512d5e5fa3d1da82 Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 16:48:04 +0400 Subject: [PATCH 04/14] fix: statemind - Incorrect operator power calculation --- src/managers/VaultManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/VaultManager.sol b/src/managers/VaultManager.sol index 0cf365f..8f75d92 100644 --- a/src/managers/VaultManager.sol +++ b/src/managers/VaultManager.sol @@ -435,7 +435,7 @@ abstract contract VaultManager is NetworkStorage, SlashingWindowStorage, Capture address[] memory vaults = _activeVaultsAt(timestamp, operator); uint160[] memory subnetworks = _activeSubnetworksAt(timestamp); - return _getOperatorPower(operator, vaults, subnetworks); + return _getOperatorPowerAt(timestamp, operator, vaults, subnetworks); } /** From 4d9e63bf54c4dc9e242bf9df84afaa2b00c25a4e Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 16:49:46 +0400 Subject: [PATCH 05/14] fix: statemind - Zero check for owner --- .../managers/access/OwnableAccessManager.sol | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/extensions/managers/access/OwnableAccessManager.sol b/src/extensions/managers/access/OwnableAccessManager.sol index 7d6000e..a8ef91d 100644 --- a/src/extensions/managers/access/OwnableAccessManager.sol +++ b/src/extensions/managers/access/OwnableAccessManager.sol @@ -30,16 +30,15 @@ abstract contract OwnableAccessManager is AccessManager, IOwnableAccessManager { function __OwnableAccessManager_init( address owner_ ) internal onlyInitializing { + if (owner_ == address(0)) { + revert InvalidOwner(address(0)); + } _setOwner(owner_); } function _setOwner( address owner_ ) private { - if (owner_ == address(0)) { - revert InvalidOwner(address(0)); - } - bytes32 location = OwnableAccessManagerStorageLocation; assembly { sstore(location, owner_) @@ -69,6 +68,9 @@ abstract contract OwnableAccessManager is AccessManager, IOwnableAccessManager { function setOwner( address owner_ ) public checkAccess { + if (owner_ == address(0)) { + revert InvalidOwner(address(0)); + } _setOwner(owner_); } From 89134d869b89dafbc85033312d8b58119b5f06db Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 16:56:53 +0400 Subject: [PATCH 06/14] fix: statemind - Missing operator update hook --- src/extensions/operators/BaseOperators.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensions/operators/BaseOperators.sol b/src/extensions/operators/BaseOperators.sol index bb79ceb..6221764 100644 --- a/src/extensions/operators/BaseOperators.sol +++ b/src/extensions/operators/BaseOperators.sol @@ -20,7 +20,7 @@ abstract contract BaseOperators is BaseMiddleware { function _registerOperatorImpl(address operator, bytes memory key, address vault) internal virtual { _beforeRegisterOperator(operator, key, vault); _registerOperator(operator); - _updateKey(operator, key); + _updateOperatorKeyImpl(operator, key); if (vault != address(0)) { _beforeRegisterOperatorVault(operator, vault); _registerOperatorVault(operator, vault); From 1f7eb1df91f502cc15cc6fef000c0f8b4093df71 Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 18:40:53 +0400 Subject: [PATCH 07/14] fix: statemind - Missing Veto Slasher consideration --- .../simple-pos-network/SimplePosMiddleware.sol | 11 ++--------- .../SelfRegisterSqrtTaskMiddleware.sol | 11 ++--------- src/examples/sqrt-task-network/SqrtTaskMiddleware.sol | 11 ++--------- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/examples/simple-pos-network/SimplePosMiddleware.sol b/src/examples/simple-pos-network/SimplePosMiddleware.sol index 6ec96f1..eca7141 100644 --- a/src/examples/simple-pos-network/SimplePosMiddleware.sol +++ b/src/examples/simple-pos-network/SimplePosMiddleware.sol @@ -178,15 +178,8 @@ contract SimplePosMiddleware is } } - function executeSlash( - uint48 epochStart, - address vault, - bytes32 subnetwork, - address operator, - uint256 amount, - bytes memory hints - ) external checkAccess { - _slashVault(epochStart, vault, subnetwork, operator, amount, hints); + function executeSlash(address vault, uint256 slashIndex, bytes memory hints) external checkAccess { + _executeSlash(vault, slashIndex, hints); } function _checkCanSlash(uint48 epochStart, bytes32 key, address operator) internal view { diff --git a/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol index ae6ed35..4150eb6 100644 --- a/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol @@ -200,15 +200,8 @@ contract SelfRegisterSqrtTaskMiddleware is } } - function executeSlash( - uint48 epochStart, - address vault, - bytes32 subnetwork, - address operator, - uint256 amount, - bytes memory hints - ) external checkAccess { - _slashVault(epochStart, vault, subnetwork, operator, amount, hints); + function executeSlash(address vault, uint256 slashIndex, bytes memory hints) external checkAccess { + _executeSlash(vault, slashIndex, hints); } function _beforeRegisterOperatorVault(address operator, address vault) internal override { diff --git a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol index faeb767..d4628b8 100644 --- a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol @@ -166,14 +166,7 @@ contract SqrtTaskMiddleware is } } - function executeSlash( - uint48 epochStart, - address vault, - bytes32 subnetwork, - address operator, - uint256 amount, - bytes memory hints - ) external checkAccess { - _slashVault(epochStart, vault, subnetwork, operator, amount, hints); + function executeSlash(address vault, uint256 slashIndex, bytes memory hints) external checkAccess { + _executeSlash(vault, slashIndex, hints); } } From f5817d08e5900a3e68e6f368b2a53964ae8d7309 Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 18:57:12 +0400 Subject: [PATCH 08/14] fix: statemind - The SelfRegisterOperators contract functionality breaks the forced pause --- .../ForcePauseSelfRegisterOperators.sol | 20 +++++++------------ src/managers/VaultManager.sol | 2 +- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/extensions/operators/ForcePauseSelfRegisterOperators.sol b/src/extensions/operators/ForcePauseSelfRegisterOperators.sol index ed5f3f5..bc55fa3 100644 --- a/src/extensions/operators/ForcePauseSelfRegisterOperators.sol +++ b/src/extensions/operators/ForcePauseSelfRegisterOperators.sol @@ -40,9 +40,8 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor ) external checkAccess { ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); $.forcePaused[operator] = true; - _beforePauseOperator(operator); if (_operatorWasActiveAt(_now(), operator)) { - _pauseOperator(operator); + _pauseOperatorImpl(operator); } } @@ -57,8 +56,7 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor if (!_isOperatorRegistered(operator)) { return; } - _beforeUnpauseOperator(operator); - _unpauseOperator(operator); + _unpauseOperatorImpl(operator); } /** @@ -67,8 +65,7 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor function forceUnregisterOperator( address operator ) external checkAccess { - _beforeUnregisterOperator(operator); - _unregisterOperator(operator); + _unregisterOperatorImpl(operator); } /** @@ -77,9 +74,8 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor function forcePauseOperatorVault(address operator, address vault) external checkAccess { ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); $.forcePausedVault[operator][vault] = true; - _beforePauseOperatorVault(operator, vault); - if (_operatorVaultWasActiveAt(_now(), operator, vault)) { - _pauseOperatorVault(operator, vault); + if (_operatorVaultWasActiveAt(_now() + 1, operator, vault)) { + _pauseOperatorVaultImpl(operator, vault); } } @@ -93,16 +89,14 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor if (!s._vaultOperator.contains(vault)) { return; } - _beforeUnpauseOperatorVault(operator, vault); - _unpauseOperatorVault(operator, vault); + _unpauseOperatorVaultImpl(operator, vault); } /** * @inheritdoc IForcePauseSelfRegisterOperators */ function forceUnregisterOperatorVault(address operator, address vault) external checkAccess { - _beforeUnregisterOperatorVault(operator, vault); - _unregisterOperatorVault(operator, vault); + _unregisterOperatorVaultImpl(operator, vault); } /** diff --git a/src/managers/VaultManager.sol b/src/managers/VaultManager.sol index 8f75d92..fab07ba 100644 --- a/src/managers/VaultManager.sol +++ b/src/managers/VaultManager.sol @@ -689,7 +689,7 @@ abstract contract VaultManager is NetworkStorage, SlashingWindowStorage, Capture function _executeSlash( address vault, uint256 slashIndex, - bytes calldata hints + bytes memory hints ) internal returns (uint256 slashedAmount) { address slasher = IVault(vault).slasher(); uint64 slasherType = IEntity(slasher).TYPE(); From 7ae51d69f3985fc37730e7c10e0a4b29a370cd10 Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 22:12:04 +0400 Subject: [PATCH 09/14] fix: An operator can always avoid slashing in SqrtTaskMiddleware like contracts --- .../SelfRegisterSqrtTaskMiddleware.sol | 14 +++++++++++--- .../sqrt-task-network/SqrtTaskMiddleware.sol | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol index 4150eb6..3bfcde4 100644 --- a/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol @@ -16,7 +16,7 @@ import {SharedVaults} from "../../extensions/SharedVaults.sol"; import {SelfRegisterOperators} from "../../extensions/operators/SelfRegisterOperators.sol"; import {ECDSASig} from "../../extensions/managers/sigs/ECDSASig.sol"; -import {OwnableAccessManager} from "../../extensions/managers/access/OwnableAccessManager.sol"; +import {OzAccessControl} from "../../extensions/managers/access/OzAccessControl.sol"; import {KeyManagerAddress} from "../../extensions/managers/keys/KeyManagerAddress.sol"; import {TimestampCapture} from "../../extensions/managers/capture-timestamps/TimestampCapture.sol"; import {EqualStakePower} from "../../extensions/managers/stake-powers/EqualStakePower.sol"; @@ -33,7 +33,7 @@ contract SelfRegisterSqrtTaskMiddleware is SelfRegisterOperators, ECDSASig, KeyManagerAddress, - OwnableAccessManager, + OzAccessControl, TimestampCapture, EqualStakePower { @@ -56,6 +56,7 @@ contract SelfRegisterSqrtTaskMiddleware is } bytes32 private constant COMPLETE_TASK_TYPEHASH = keccak256("CompleteTask(uint256 taskIndex,uint256 answer)"); + bytes32 private constant COMPLETE_TASK_ROLE = keccak256("COMPLETE_TASK_ROLE"); uint256 public constant MAX_OPERATOR_VAULTS = 20; @@ -84,8 +85,9 @@ contract SelfRegisterSqrtTaskMiddleware is ) internal initializer { INetworkRegistry(networkRegistry).registerNetwork(); __BaseMiddleware_init(address(this), slashingWindow, vaultRegistry, operatorRegistry, operatorNetOptin, reader); - __OwnableAccessManager_init(owner); + __OzAccessControl_init(owner); __SelfRegisterOperators_init("SelfRegisterSqrtTaskMiddleware"); + _setSelectorRole(this.completeTask.selector, COMPLETE_TASK_ROLE); } function createTask(uint256 value, address validator) external returns (uint256 taskIndex) { @@ -204,6 +206,12 @@ contract SelfRegisterSqrtTaskMiddleware is _executeSlash(vault, slashIndex, hints); } + // it's intended that operator can test slashing by themself + function _beforeRegisterOperator(address operator, bytes memory key, address vault) internal override { + super._beforeRegisterOperator(operator, key, vault); + _grantRole(COMPLETE_TASK_ROLE, operator); + } + function _beforeRegisterOperatorVault(address operator, address vault) internal override { super._beforeRegisterOperatorVault(operator, vault); if (_operatorVaultsLength(operator) >= MAX_OPERATOR_VAULTS) { diff --git a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol index d4628b8..bd6b021 100644 --- a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol @@ -13,7 +13,7 @@ import {BaseMiddleware} from "../../middleware/BaseMiddleware.sol"; import {SharedVaults} from "../../extensions/SharedVaults.sol"; import {Operators} from "../../extensions/operators/Operators.sol"; -import {OwnableAccessManager} from "../../extensions/managers/access/OwnableAccessManager.sol"; +import {OzAccessControl} from "../../extensions/managers/access/OzAccessControl.sol"; import {NoKeyManager} from "../../extensions/managers/keys/NoKeyManager.sol"; import {TimestampCapture} from "../../extensions/managers/capture-timestamps/TimestampCapture.sol"; import {EqualStakePower} from "../../extensions/managers/stake-powers/EqualStakePower.sol"; @@ -23,7 +23,7 @@ contract SqrtTaskMiddleware is Operators, NoKeyManager, EIP712, - OwnableAccessManager, + OzAccessControl, TimestampCapture, EqualStakePower { @@ -45,6 +45,7 @@ contract SqrtTaskMiddleware is } bytes32 private constant COMPLETE_TASK_TYPEHASH = keccak256("CompleteTask(uint256 taskIndex,uint256 answer)"); + bytes32 private constant COMPLETE_TASK_ROLE = keccak256("COMPLETE_TASK_ROLE"); Task[] public tasks; @@ -70,7 +71,8 @@ contract SqrtTaskMiddleware is address owner ) internal initializer { __BaseMiddleware_init(network, slashingWindow, vaultRegistry, operatorRegistry, operatorNetOptin, reader); - __OwnableAccessManager_init(owner); + __OzAccessControl_init(owner); + _setSelectorRole(this.completeTask.selector, COMPLETE_TASK_ROLE); } function createTask(uint256 value, address operator) external returns (uint256 taskIndex) { @@ -169,4 +171,10 @@ contract SqrtTaskMiddleware is function executeSlash(address vault, uint256 slashIndex, bytes memory hints) external checkAccess { _executeSlash(vault, slashIndex, hints); } + + // it's intended that operator can test slashing by themself + function _beforeRegisterOperator(address operator, bytes memory key, address vault) internal override { + super._beforeRegisterOperator(operator, key, vault); + _grantRole(COMPLETE_TASK_ROLE, operator); + } } From 329e62b8fff5e97c7c7eb1458db0b10939763373 Mon Sep 17 00:00:00 2001 From: alrxy Date: Wed, 15 Jan 2025 22:14:51 +0400 Subject: [PATCH 10/14] fix: statemind - Incorrect storage slot location --- src/extensions/managers/keys/KeyManagerAddress.sol | 2 +- src/managers/storages/NetworkStorage.sol | 2 +- src/managers/storages/SlashingWindowStorage.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/extensions/managers/keys/KeyManagerAddress.sol b/src/extensions/managers/keys/KeyManagerAddress.sol index fe889dc..a7a57ff 100644 --- a/src/extensions/managers/keys/KeyManagerAddress.sol +++ b/src/extensions/managers/keys/KeyManagerAddress.sol @@ -28,7 +28,7 @@ abstract contract KeyManagerAddress is KeyManager { // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.KeyManagerAddress")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant KeyManagerAddressStorageLocation = - 0x3da47716e6090d5a5545e03387f4dac112d37cd069a5573bb81de8579bd9dc00; + 0xb864e827a56afd83aa8f7940e556fe526831aa2e6001c2c692580b8e7a7d1d00; function _getKeyManagerAddressStorage() internal pure returns (KeyManagerAddressStorage storage s) { bytes32 location = KeyManagerAddressStorageLocation; diff --git a/src/managers/storages/NetworkStorage.sol b/src/managers/storages/NetworkStorage.sol index 4914cb5..743c590 100644 --- a/src/managers/storages/NetworkStorage.sol +++ b/src/managers/storages/NetworkStorage.sol @@ -10,7 +10,7 @@ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Ini */ abstract contract NetworkStorage is Initializable { // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.NetworkStorage")) - 1)) & ~bytes32(uint256(0xff)) - bytes32 private constant NetworkStorageLocation = 0x779150488f5e984d1f840ba606e388ada6c73b44f261274c3595c61a30023e00; + bytes32 private constant NetworkStorageLocation = 0x933223a21808ea6583da836861e2265bfa3c7e3b9070740cd75dc9ff6fb41700; /** * @notice Initializes the NetworkManager contract diff --git a/src/managers/storages/SlashingWindowStorage.sol b/src/managers/storages/SlashingWindowStorage.sol index 9a07e10..660805b 100644 --- a/src/managers/storages/SlashingWindowStorage.sol +++ b/src/managers/storages/SlashingWindowStorage.sol @@ -11,7 +11,7 @@ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Ini abstract contract SlashingWindowStorage is Initializable { // keccak256(abi.encode(uint256(keccak256("symbiotic.storage.SlashingWindowStorage")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant SlashingWindowStorageLocation = - 0x52becd5b30d67421b1f63b9d90d513daf82b3973912d3edfdac9468c1743c000; + 0x937e0d2984afc3afaa413d74098ba180cc0c6aae6527cc2713827ed6bc72f200; /** * @notice Initializes the SlashingWindowStorage contract From 537fd838ccf06c072ca9235cae781529e4768c5d Mon Sep 17 00:00:00 2001 From: alrxy Date: Fri, 17 Jan 2025 19:21:38 +0400 Subject: [PATCH 11/14] fix: statemind - Unable to unregister Operator and Operator Vault after forcePause --- .../ForcePauseSelfRegisterOperators.sol | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/extensions/operators/ForcePauseSelfRegisterOperators.sol b/src/extensions/operators/ForcePauseSelfRegisterOperators.sol index bc55fa3..9fef3d2 100644 --- a/src/extensions/operators/ForcePauseSelfRegisterOperators.sol +++ b/src/extensions/operators/ForcePauseSelfRegisterOperators.sol @@ -40,7 +40,7 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor ) external checkAccess { ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); $.forcePaused[operator] = true; - if (_operatorWasActiveAt(_now(), operator)) { + if (_operatorWasActiveAt(_now() + 1, operator)) { _pauseOperatorImpl(operator); } } @@ -112,15 +112,14 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor } /** - * @notice Override to prevent unregistering force-paused operators + * @notice Override to prevent registering force-paused operators * @param operator The operator address + * @param key The operator's public key + * @param vault The vault address */ - function _beforeUnregisterOperator( - address operator - ) internal virtual override { - super._beforeUnregisterOperator(operator); - ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); - if ($.forcePaused[operator]) revert OperatorForcePaused(); + function _beforeRegisterOperator(address operator, bytes memory key, address vault) internal virtual override { + super._beforeRegisterOperator(operator, key, vault); + if (_operatorForcePaused(operator)) revert OperatorForcePaused(); } /** @@ -130,18 +129,28 @@ abstract contract ForcePauseSelfRegisterOperators is SelfRegisterOperators, IFor */ function _beforeUnpauseOperatorVault(address operator, address vault) internal virtual override { super._beforeUnpauseOperatorVault(operator, vault); - ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); - if ($.forcePausedVault[operator][vault]) revert OperatorVaultForcePaused(); + if (_operatorVaultForcePaused(operator, vault)) revert OperatorVaultForcePaused(); } /** - * @notice Override to prevent unregistering force-paused operator-vault pairs + * @notice Override to prevent registering force-paused operator-vault pairs * @param operator The operator address * @param vault The vault address */ - function _beforeUnregisterOperatorVault(address operator, address vault) internal virtual override { - super._beforeUnregisterOperatorVault(operator, vault); + function _beforeRegisterOperatorVault(address operator, address vault) internal virtual override { + super._beforeRegisterOperatorVault(operator, vault); + if (_operatorVaultForcePaused(operator, vault)) revert OperatorVaultForcePaused(); + } + + function _operatorForcePaused( + address operator + ) private view returns (bool) { + ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); + return $.forcePaused[operator]; + } + + function _operatorVaultForcePaused(address operator, address vault) private view returns (bool) { ForcePauseSelfRegisterOperatorsStorage storage $ = _getForcePauseStorage(); - if ($.forcePausedVault[operator][vault]) revert OperatorVaultForcePaused(); + return $.forcePausedVault[operator][vault]; } } From 6020ffae584248f8fe2e542b3197262798f20cd1 Mon Sep 17 00:00:00 2001 From: alrxy Date: Mon, 20 Jan 2025 15:45:46 +0400 Subject: [PATCH 12/14] Revert "fix: An operator can always avoid slashing in SqrtTaskMiddleware like contracts" This reverts commit 7ae51d69f3985fc37730e7c10e0a4b29a370cd10. --- .../SelfRegisterSqrtTaskMiddleware.sol | 14 +++----------- .../sqrt-task-network/SqrtTaskMiddleware.sol | 14 +++----------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol index 3bfcde4..4150eb6 100644 --- a/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol @@ -16,7 +16,7 @@ import {SharedVaults} from "../../extensions/SharedVaults.sol"; import {SelfRegisterOperators} from "../../extensions/operators/SelfRegisterOperators.sol"; import {ECDSASig} from "../../extensions/managers/sigs/ECDSASig.sol"; -import {OzAccessControl} from "../../extensions/managers/access/OzAccessControl.sol"; +import {OwnableAccessManager} from "../../extensions/managers/access/OwnableAccessManager.sol"; import {KeyManagerAddress} from "../../extensions/managers/keys/KeyManagerAddress.sol"; import {TimestampCapture} from "../../extensions/managers/capture-timestamps/TimestampCapture.sol"; import {EqualStakePower} from "../../extensions/managers/stake-powers/EqualStakePower.sol"; @@ -33,7 +33,7 @@ contract SelfRegisterSqrtTaskMiddleware is SelfRegisterOperators, ECDSASig, KeyManagerAddress, - OzAccessControl, + OwnableAccessManager, TimestampCapture, EqualStakePower { @@ -56,7 +56,6 @@ contract SelfRegisterSqrtTaskMiddleware is } bytes32 private constant COMPLETE_TASK_TYPEHASH = keccak256("CompleteTask(uint256 taskIndex,uint256 answer)"); - bytes32 private constant COMPLETE_TASK_ROLE = keccak256("COMPLETE_TASK_ROLE"); uint256 public constant MAX_OPERATOR_VAULTS = 20; @@ -85,9 +84,8 @@ contract SelfRegisterSqrtTaskMiddleware is ) internal initializer { INetworkRegistry(networkRegistry).registerNetwork(); __BaseMiddleware_init(address(this), slashingWindow, vaultRegistry, operatorRegistry, operatorNetOptin, reader); - __OzAccessControl_init(owner); + __OwnableAccessManager_init(owner); __SelfRegisterOperators_init("SelfRegisterSqrtTaskMiddleware"); - _setSelectorRole(this.completeTask.selector, COMPLETE_TASK_ROLE); } function createTask(uint256 value, address validator) external returns (uint256 taskIndex) { @@ -206,12 +204,6 @@ contract SelfRegisterSqrtTaskMiddleware is _executeSlash(vault, slashIndex, hints); } - // it's intended that operator can test slashing by themself - function _beforeRegisterOperator(address operator, bytes memory key, address vault) internal override { - super._beforeRegisterOperator(operator, key, vault); - _grantRole(COMPLETE_TASK_ROLE, operator); - } - function _beforeRegisterOperatorVault(address operator, address vault) internal override { super._beforeRegisterOperatorVault(operator, vault); if (_operatorVaultsLength(operator) >= MAX_OPERATOR_VAULTS) { diff --git a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol index bd6b021..d4628b8 100644 --- a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol @@ -13,7 +13,7 @@ import {BaseMiddleware} from "../../middleware/BaseMiddleware.sol"; import {SharedVaults} from "../../extensions/SharedVaults.sol"; import {Operators} from "../../extensions/operators/Operators.sol"; -import {OzAccessControl} from "../../extensions/managers/access/OzAccessControl.sol"; +import {OwnableAccessManager} from "../../extensions/managers/access/OwnableAccessManager.sol"; import {NoKeyManager} from "../../extensions/managers/keys/NoKeyManager.sol"; import {TimestampCapture} from "../../extensions/managers/capture-timestamps/TimestampCapture.sol"; import {EqualStakePower} from "../../extensions/managers/stake-powers/EqualStakePower.sol"; @@ -23,7 +23,7 @@ contract SqrtTaskMiddleware is Operators, NoKeyManager, EIP712, - OzAccessControl, + OwnableAccessManager, TimestampCapture, EqualStakePower { @@ -45,7 +45,6 @@ contract SqrtTaskMiddleware is } bytes32 private constant COMPLETE_TASK_TYPEHASH = keccak256("CompleteTask(uint256 taskIndex,uint256 answer)"); - bytes32 private constant COMPLETE_TASK_ROLE = keccak256("COMPLETE_TASK_ROLE"); Task[] public tasks; @@ -71,8 +70,7 @@ contract SqrtTaskMiddleware is address owner ) internal initializer { __BaseMiddleware_init(network, slashingWindow, vaultRegistry, operatorRegistry, operatorNetOptin, reader); - __OzAccessControl_init(owner); - _setSelectorRole(this.completeTask.selector, COMPLETE_TASK_ROLE); + __OwnableAccessManager_init(owner); } function createTask(uint256 value, address operator) external returns (uint256 taskIndex) { @@ -171,10 +169,4 @@ contract SqrtTaskMiddleware is function executeSlash(address vault, uint256 slashIndex, bytes memory hints) external checkAccess { _executeSlash(vault, slashIndex, hints); } - - // it's intended that operator can test slashing by themself - function _beforeRegisterOperator(address operator, bytes memory key, address vault) internal override { - super._beforeRegisterOperator(operator, key, vault); - _grantRole(COMPLETE_TASK_ROLE, operator); - } } From 81881a782a3f13a8f9ebbe670493efcf99f2c3d8 Mon Sep 17 00:00:00 2001 From: alrxy Date: Mon, 20 Jan 2025 15:45:53 +0400 Subject: [PATCH 13/14] Revert "fix: statemind - Slashing in the future" This reverts commit f7a679b8f918316fa1dfe3851499844b5a4145e7. --- src/managers/VaultManager.sol | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/managers/VaultManager.sol b/src/managers/VaultManager.sol index fab07ba..6dca52f 100644 --- a/src/managers/VaultManager.sol +++ b/src/managers/VaultManager.sol @@ -43,7 +43,6 @@ abstract contract VaultManager is NetworkStorage, SlashingWindowStorage, Capture error NoSlasher(); error TooOldTimestampSlash(); error NotOperatorSpecificVault(); - error FutureTimestampSlash(); /// @custom:storage-location erc7201:symbiotic.storage.VaultManager struct VaultManagerStorage { @@ -645,11 +644,6 @@ abstract contract VaultManager is NetworkStorage, SlashingWindowStorage, Capture bytes memory hints ) internal returns (uint256 response) { VaultManagerStorage storage $ = _getVaultManagerStorage(); - - if (timestamp > _now()) { - revert FutureTimestampSlash(); - } - if (!($._sharedVaults.contains(vault) || $._operatorVaults[operator].contains(vault))) { revert NotOperatorVault(); } From 9f22b9a43c2dfb48b1341af625e24b6e456a2005 Mon Sep 17 00:00:00 2001 From: alrxy Date: Mon, 20 Jan 2025 15:46:58 +0400 Subject: [PATCH 14/14] chore: sqrt task examples warning --- .../sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol | 1 + src/examples/sqrt-task-network/SqrtTaskMiddleware.sol | 1 + 2 files changed, 2 insertions(+) diff --git a/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol index 4150eb6..5233fb2 100644 --- a/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SelfRegisterSqrtTaskMiddleware.sol @@ -21,6 +21,7 @@ import {KeyManagerAddress} from "../../extensions/managers/keys/KeyManagerAddres import {TimestampCapture} from "../../extensions/managers/capture-timestamps/TimestampCapture.sol"; import {EqualStakePower} from "../../extensions/managers/stake-powers/EqualStakePower.sol"; +// WARING: this is a simple example, it's not secure and should not be used in production /** * @title SelfRegisterSqrtTaskMiddleware * @notice Middleware for managing sqrt computation tasks with self-registering operators diff --git a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol index d4628b8..034a409 100644 --- a/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol +++ b/src/examples/sqrt-task-network/SqrtTaskMiddleware.sol @@ -18,6 +18,7 @@ import {NoKeyManager} from "../../extensions/managers/keys/NoKeyManager.sol"; import {TimestampCapture} from "../../extensions/managers/capture-timestamps/TimestampCapture.sol"; import {EqualStakePower} from "../../extensions/managers/stake-powers/EqualStakePower.sol"; +// WARING: this is a simple example, it's not secure and should not be used in production contract SqrtTaskMiddleware is SharedVaults, Operators,