Skip to content

Commit

Permalink
fixes(m2-mainnet): combined pr for all m2-mainnet fixs (Layr-Labs#162)
Browse files Browse the repository at this point in the history
* update: change core submodule branch

* fix: make commit hook executable again (Layr-Labs#160)

Co-authored-by: steven <[email protected]>

* ci: add ci to run on PRs to m2-mainnet-fixes (Layr-Labs#159)

Co-authored-by: steven <[email protected]>

* refactor: update minWithdrawalDelayBLocks variable (Layr-Labs#152)

* refactor: minWithdrawalDelayBLocks from core

* fix: core contracts commit and tests

* feat: add avs directory to service manager

* fix: rebase off updated bls sig checker; update integration tests

* Add AVS Directory Support to Service Manager (Layr-Labs#156)

* update: change core submodule branch

* feat: add avs directory to service manager

* fix: rebase off updated bls sig checker; update integration tests

* fix: core contracts commit and tests

* feat: add avs directory to service manager

* fix: rebase off updated bls sig checker; update integration tests

* fix: conflicts

---------

Co-authored-by: 8sunyuan <[email protected]>

* fix: submodule commit

* fix: rebase changes

* Add AVS Directory Support to Service Manager (Layr-Labs#156)

* update: change core submodule branch

* feat: add avs directory to service manager

* fix: rebase off updated bls sig checker; update integration tests

* fix: core contracts commit and tests

* feat: add avs directory to service manager

* fix: rebase off updated bls sig checker; update integration tests

* fix: conflicts

---------

Co-authored-by: 8sunyuan <[email protected]>

* fix: submodule commit

* fix: rebase changes

* Add AVS Directory Support to Service Manager (Layr-Labs#156)

* update: change core submodule branch

* feat: add avs directory to service manager

* fix: rebase off updated bls sig checker; update integration tests

* fix: core contracts commit and tests

* feat: add avs directory to service manager

* fix: rebase off updated bls sig checker; update integration tests

* fix: conflicts

---------

Co-authored-by: 8sunyuan <[email protected]>

* fix: submodule commit

* docs: AVSRegistry -> AVSDirectory

---------

Co-authored-by: Yash Patil <[email protected]>

* fix: churner (Layr-Labs#157)

* fix: submodule (Layr-Labs#164)

* test: fix flaky tests by removing bogosort (Layr-Labs#163)

* test: fix flaky tests by removing bogosort

* test: fix flaky test by rejecting empty addr inputs

* chore: storage gaps and nits (Layr-Labs#155)

* chore: add storage gaps to BLSSignatureChecker and ServiceManagerBase

* chore: ServiceManagerBase to abstract and create mock

* chore: use onlyInitializing in Base and initializer in mock

* chore: add storage gaps to BLSSignatureChecker and ServiceManagerBase

* chore: ServiceManagerBase to abstract and create mock

* chore: use onlyInitializing in Base and initializer in mock

* fix: core submodules

---------

Co-authored-by: steven <[email protected]>

* chore: eigenlayer-contracts (Layr-Labs#168)

* test/refactor: gas scenarios for updateOperators (Layr-Labs#170)

* test: gas scenarios for updateOperators

* refactor: using one call for operatorShares

* test: updateOperators 200 operators

* test: gas scenarios for updateOperators

* refactor: using one call for operatorShares

* test: updateOperators 200 operators

* fix: comments

* chore: less restrictive license for library code (Layr-Labs#177)

MIT instead of BSL-MIT mix

* docs: update README to point at deployment info (Layr-Labs#178)

* feat: minor gas optimization (Layr-Labs#183)

slightly less memory ops in `orderedBytesArrayToBitmap` fnc

* fix: include missing fields in TYPEHASH defintion (Layr-Labs#182)

* fix: include missing fields in TYPEHASH defintion

the `salt` and `expiry` fields were missing from the `OPERATOR_CHURN_APPROVAL_TYPEHASH` def

* fix: correct definition of OperatorKickParam inside of typehash def

* docs: fix grammer and inaccurate naming (Layr-Labs#179)

* fix: prevent use of current block as reference block number (Layr-Labs#181)

* chore: clean up loops to iterate downward and remove unneeded checks (Layr-Labs#180)

* chore: clean up loops to iterate downward and remove unneeded checks

* docs: clarifying comments around quorum existence checks

* docs: clarify usage of msgHash (Layr-Labs#184)

---------

Co-authored-by: Yash Patil <[email protected]>
Co-authored-by: steven <[email protected]>
Co-authored-by: Michael Sun <[email protected]>
Co-authored-by: quaq <[email protected]>
Co-authored-by: Alex <[email protected]>
Co-authored-by: ChaoticWalrus <[email protected]>
  • Loading branch information
7 people authored Feb 16, 2024
1 parent 6e95af9 commit 2809671
Show file tree
Hide file tree
Showing 38 changed files with 1,769 additions and 207 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
branches:
- master
- m2-mainnet
- m2-mainnet-fixes
pull_request:

env:
Expand Down
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[submodule "lib/eigenlayer-contracts"]
path = lib/eigenlayer-contracts
url = https://github.com/Layr-labs/eigenlayer-contracts
branch = m2-mainnet
branch = m2-mainnet-fixes
[submodule "lib/ds-test"]
path = lib/ds-test
url = https://github.com/dapphub/ds-test
Expand Down
Empty file modified .husky/commit-msg
100644 → 100755
Empty file.
29 changes: 2 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@

EigenLayer is a set of smart contracts deployed on Ethereum that enable restaking of assets to secure new services called AVSs (actively validated services). The core contracts that enable these features can be found in the [`eigenlayer-contracts` repo][core-repo].

This repo contains smart contracts used to create an AVS that interacts with the EigenLayer core contracts.
This repo contains smart contracts used to create an AVS that interacts with the EigenLayer core contracts. Because these contracts are meant to be used by any AVS, there is no single deployment. However, you can see EigenDA's deployment info on our [docs site](https://docs.eigenlayer.xyz/eigenda/deployed-contracts).

## Getting Started

* [Documentation](#documentation)
* [Building and Running Tests](#building-and-running-tests)
* [Deployments](#deployments)

## Documentation

Expand Down Expand Up @@ -39,28 +38,4 @@ foundryup

forge build
forge test
```

## Deployments

The contracts in this repo are meant to be deployed by each AVS that wants to use them. The addresses listed below refer to EigenDA's deployment, and are included as an example.

### Current Mainnet Deployment

No contracts have been deployed to mainnet yet.

### Current Testnet Deployment

The current testnet deployment is from our M2 beta release, which is a slightly older version of this repo. You can view the deployed contract addresses below, or check out the [`v0.1.0`](https://github.com/Layr-Labs/eigenlayer-middleware/tree/v0.1.0-m2-goerli) branch in "Releases".


| Name | Solidity | Proxy | Implementation | Notes |
| -------- | -------- | -------- | -------- | -------- |
| RegistryCoordinator | [`BLSRegistryCoordinatorWithIndices.sol`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/v0.1.0-m2-goerli/src/BLSRegistryCoordinatorWithIndices.sol) | [`0x0b30...4C0B`](https://goerli.etherscan.io/address/0x0b30a3427765f136754368a4500bAca8d2a54C0B) | [`0x9A70...a0e4`](https://goerli.etherscan.io/address/0x9A70ED111FaFEC41856202536AFAA38841a9a0e4) | Proxy: [OpenZeppelin [email protected]](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.7.1/contracts/proxy/transparent/TransparentUpgradeableProxy.sol) |
| StakeRegistry | [`StakeRegistry.sol`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/v0.1.0-m2-goerli/src/StakeRegistry.sol) | [`0x5a83...A206`](https://goerli.etherscan.io/address/0x5a834d58D22742503D8f92dd2f28c866C166A206) | [`0x8741...5B98`](https://goerli.etherscan.io/address/0x8741e3a24d9517Aa19E63122A34680a9A85F5B98) | Proxy: [OpenZeppelin [email protected]](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.7.1/contracts/proxy/transparent/TransparentUpgradeableProxy.sol) |
| IndexRegistry | [`IndexRegistry.sol`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/v0.1.0-m2-goerli/src/IndexRegistry.sol) | [`0xa8A1...BDF7`](https://goerli.etherscan.io/address/0xa8A14B97d556cEc3f4384C186fB99d72F015BDF7) | [`0x8cd4...8117`](https://goerli.etherscan.io/address/0x8cd4c39B713B026319e35f20B7f19baE28648117) | Proxy: [OpenZeppelin [email protected]](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.7.1/contracts/proxy/transparent/TransparentUpgradeableProxy.sol) |
| BLSApkRegistry | [`BLSPubkeyRegistry.sol`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/v0.1.0-m2-goerli/src/BLSPubkeyRegistry.sol) | [`0xD8fC...BEcA`](https://goerli.etherscan.io/address/0xD8fCD5c9103962DE37E375EF9dB62cCf39D5BEcA) | [`0x4C9D...aFb8`](https://goerli.etherscan.io/address/0x4C9D23fd901d3d98e75BdcC6a8AC9bA81d8DaFb8) | Proxy: [OpenZeppelin [email protected]](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.7.1/contracts/proxy/transparent/TransparentUpgradeableProxy.sol) |
| BLSPubkeyCompendium <br />(deprecated) | [`BLSPublicKeyCompendium.sol`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/v0.1.0-m2-goerli/src/BLSPublicKeyCompendium.sol) | - | [`0xc81d...1b19`](https://goerli.etherscan.io/address/0xc81d3963087fe09316cd1e032457989c7ac91b19) | |
| OperatorStateRetriever | [`BLSOperatorStateRetriever.sol`](https://github.com/Layr-Labs/eigenlayer-middleware/blob/v0.1.0-m2-goerli/src/BLSOperatorStateRetriever.sol) | - | [`0x737d...a3a3`](https://goerli.etherscan.io/address/0x737dd62816a9392e84fa21c531af77c00816a3a3) | |
| ProxyAdmin | [OpenZeppelin [email protected]](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.7.1/contracts/proxy/transparent/ProxyAdmin.sol) | - | [`0xbe85...aF3e`](https://goerli.etherscan.io/address/0xbe85B38b6086A45350947DD6dA6d78cc2E4BaF3e) | |
| EigenDAServiceManager | [`eigenda/EigenDAServiceManager.sol`](https://github.com/Layr-Labs/eigenda/blob/f599513723a17ad7bd5693287f75325007deec19/contracts/EigenDAServiceManager.sol#L4831) | [`0x9FcE...0010`](https://goerli.etherscan.io/address/0x9FcE30E01a740660189bD8CbEaA48Abd36040010) | [`0x1261...9606`](https://goerli.etherscan.io/address/0x12612f42bc1f09680c3d0c8dae72d5cd534c9606) | Proxy: [OpenZeppelin [email protected]](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.7.1/contracts/proxy/transparent/TransparentUpgradeableProxy.sol) |
```
5 changes: 3 additions & 2 deletions docs/BLSSignatureChecker.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct QuorumStakeTotals {
The goal of this method is to allow an AVS to validate a BLS signature formed from the aggregate pubkey ("apk") of Operators registered in one or more quorums at some `referenceBlockNumber`.

Some notes on method parameters:
* `msgHash` is the hash being signed by the apk. Note that the caller is responsible for ensuring `msgHash` is a hash! If someone can provide arbitrary input, it may be possible to tamper with signature verification.
* `referenceBlockNumber` is the reason each registry contract keeps historical states: so that lookups can be performed on each registry's info at a particular block. This is important because Operators may sign some data on behalf of an AVS, then deregister from one or more of the AVS's quorums. Historical states allow signature validation to be performed against a "fixed point" in AVS/quorum history.
* `quorumNumbers` is used to perform signature validation across one *or more* quorums. Also, Operators may be registered for more than one quorum - and for each quorum an Operator is registered for, that Operator's pubkey is included in that quorum's apk within the `BLSApkRegistry`. This means that, when calculating an apk across multiple `quorumNumbers`, Operators registered for more than one of these quorums will have their pubkey included more than once in the total apk.
* `params` contains both a signature from all signing Operators, as well as several fields that identify registered, non-signing Operators. While non-signing Operators haven't contributed to the signature, but need to be accounted for because, as Operators registered for one or more signing quorums, their public keys are included in that quorum's apk. Essentially, in order to validate the signature, nonsigners' public keys need to be subtracted out from the total apk to derive the apk that actually signed the message.
Expand All @@ -87,11 +88,11 @@ This method performs the following steps. Note that each step involves lookups o
* Input validation:
* Quorum-related fields MUST have equal lengths: `quorumNumbers`, `params.quorumApks`, `params.quorumApkIndices`, `params.totalStakeIndices`, `params.nonSignerStakeIndices`
* Nonsigner-related fields MUST have equal lengths: `params.nonSignerPubkeys`, `params.nonSignerQuorumBitmapIndices`
* `referenceBlockNumber` MUST NOT be greater than `block.number`
* `referenceBlockNumber` MUST be less than `block.number`
* `quorumNumbers` MUST be an ordered list of valid, initialized quorums
* `params.nonSignerPubkeys` MUST ONLY contain unique pubkeys, in ascending order of their pubkey hash
* For each quorum:
* If stale stakes are forbidden (see [`BLSSignatureChecker.setStaleStakesForbidden`](#blssignaturecheckersetstalestakesforbidden)), check the last `quorumUpdateBlockNumber` is within `DelegationManager.withdrawalDelayBlocks` of `referenceBlockNumber`. This references a value in the EigenLayer core contracts - see [EigenLayer core docs][core-docs-m2] for more info.
* If stale stakes are forbidden (see [`BLSSignatureChecker.setStaleStakesForbidden`](#blssignaturecheckersetstalestakesforbidden)), check the last `quorumUpdateBlockNumber` is within `DelegationManager.minWithdrawalDelayBlocks` of `referenceBlockNumber`. This references a value in the EigenLayer core contracts - see [EigenLayer core docs][core-docs-m2] for more info.
* Validate that each `params.quorumApks` corresponds to the quorum's apk at the `referenceBlockNumber`
* For each historical state lookup, the `referenceBlockNumber` and provided index MUST point to a valid historical entry:
* `referenceBlockNumber` MUST come after the entry's `updateBlockNumber`
Expand Down
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ These histories are used by offchain code to query state at particular blocks, a
##### Hooking Into EigenLayer Core

The main thing that links an AVS to the EigenLayer core contracts is that when EigenLayer Operators register/deregister with an AVS, the AVS calls these functions in EigenLayer core:
* [`DelegationManager.registerOperatorToAVS`][core-registerToAVS]
* [`DelegationManager.deregisterOperatorFromAVS`][core-deregisterFromAVS]
* [`AVSDirectory.registerOperatorToAVS`][core-registerToAVS]
* [`AVSDirectory.deregisterOperatorFromAVS`][core-deregisterFromAVS]

These methods ensure that the Operator registering with the AVS is also registered as an Operator in EigenLayer core. In this repo, these methods are called by the `ServiceManagerBase`.

Expand Down
2 changes: 1 addition & 1 deletion lib/eigenlayer-contracts
Submodule eigenlayer-contracts updated 65 files
+2 −3 .github/workflows/certora-prover.yml
+5 −2 .github/workflows/testinparallel.yml
+3 −3 certora/specs/core/StrategyManager.spec
+18 −1 docs/README.md
+66 −0 docs/core/AVSDirectory.md
+43 −58 docs/core/DelegationManager.md
+40 −4 docs/core/StrategyManager.md
+15 −1 script/middleware/DeployOpenEigenLayer.s.sol
+10 −1 script/milestone/M2Deploy.s.sol
+30 −0 script/output/GV2_preprod_deployment_2024_30_1.json
+33 −0 script/output/M2_preprod_deployment_from_scratch.json
+1 −1 script/testing/M2_Deploy_From_Scratch.s.sol
+129 −0 script/upgrade/GoerliUpgrade2.s.sol
+5 −0 script/utils/ExistingDeploymentParser.sol
+174 −0 src/contracts/core/AVSDirectory.sol
+46 −0 src/contracts/core/AVSDirectoryStorage.sol
+105 −116 src/contracts/core/DelegationManager.sol
+14 −17 src/contracts/core/DelegationManagerStorage.sol
+47 −5 src/contracts/core/StrategyManager.sol
+8 −1 src/contracts/core/StrategyManagerStorage.sol
+67 −0 src/contracts/interfaces/IAVSDirectory.sol
+29 −66 src/contracts/interfaces/IDelegationManager.sol
+19 −0 src/contracts/interfaces/IEigenPodManager.sol
+16 −3 src/contracts/interfaces/IStrategyManager.sol
+12 −10 src/contracts/libraries/BeaconChainProofs.sol
+2 −2 src/contracts/pods/DelayedWithdrawalRouter.sol
+2 −1 src/contracts/pods/EigenPod.sol
+31 −2 src/contracts/pods/EigenPodManager.sol
+3 −1 src/contracts/pods/EigenPodManagerStorage.sol
+16 −2 src/test/Delegation.t.sol
+2 −1 src/test/DelegationFaucet.t.sol
+15 −7 src/test/DepositWithdraw.t.sol
+6 −2 src/test/EigenLayerDeployer.t.sol
+2 −1 src/test/EigenLayerTestHelper.t.sol
+50 −7 src/test/EigenPod.t.sol
+15 −0 src/test/events/IAVSDirectoryEvents.sol
+2 −3 src/test/events/IDelegationManagerEvents.sol
+7 −0 src/test/events/IEigenPodManagerEvents.sol
+63 −0 src/test/events/IStrategyManagerEvents.sol
+2 −1 src/test/harnesses/EigenPodHarness.sol
+18 −1 src/test/integration/IntegrationBase.t.sol
+42 −15 src/test/integration/IntegrationChecks.t.sol
+12 −2 src/test/integration/IntegrationDeployer.t.sol
+1 −1 src/test/integration/User.t.sol
+15 −6 src/test/integration/mocks/BeaconChainMock.t.sol
+83 −0 src/test/integration/tests/Delegate_Deposit_Queue_Complete.t.sol
+4 −4 src/test/integration/tests/Deposit_Delegate_Queue_Complete.t.sol
+394 −6 src/test/integration/tests/Deposit_Delegate_Redelegate_Complete.t.sol
+4 −4 src/test/integration/tests/Deposit_Delegate_Undelegate_Complete.t.sol
+1 −1 src/test/integration/tests/Deposit_Delegate_UpdateBalance.t.sol
+79 −0 src/test/integration/tests/Deposit_Queue_Complete.t.sol
+75 −0 src/test/integration/tests/Deposit_Register_QueueWithdrawal_Complete.t.sol
+20 −2 src/test/mocks/DelegationManagerMock.sol
+5 −0 src/test/mocks/ERC20Mock.sol
+7 −0 src/test/mocks/EigenPodManagerMock.sol
+7 −2 src/test/mocks/StrategyManagerMock.sol
+160 −0 src/test/test-data/fullWithdrawalCapellaAgainstDenebRoot.json
+162 −0 src/test/test-data/fullWithdrawalDeneb.json
+274 −0 src/test/unit/AVSDirectoryUnit.t.sol
+87 −184 src/test/unit/DelegationUnit.t.sol
+5 −5 src/test/unit/EigenPod-PodManagerUnit.t.sol
+30 −3 src/test/unit/EigenPodManagerUnit.t.sol
+11 −6 src/test/unit/EigenPodUnit.t.sol
+53 −78 src/test/unit/StrategyManagerUnit.t.sol
+28 −8 src/test/utils/ProofParsing.sol
18 changes: 9 additions & 9 deletions src/BLSApkRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -205,19 +205,19 @@ contract BLSApkRegistry is BLSApkRegistryStorage {
uint256 blockNumber
) external view returns (uint32[] memory) {
uint32[] memory indices = new uint32[](quorumNumbers.length);
for (uint i = 0; i < quorumNumbers.length; i++) {

for (uint256 i = 0; i < quorumNumbers.length; i++) {
uint8 quorumNumber = uint8(quorumNumbers[i]);
uint32 quorumApkUpdatesLength = uint32(apkHistory[quorumNumber].length);


uint256 quorumApkUpdatesLength = apkHistory[quorumNumber].length;
if (quorumApkUpdatesLength == 0 || blockNumber < apkHistory[quorumNumber][0].updateBlockNumber) {
revert(
"BLSApkRegistry.getApkIndicesAtBlockNumber: blockNumber is before the first update"
);
revert("BLSApkRegistry.getApkIndicesAtBlockNumber: blockNumber is before the first update");
}

for (uint32 j = 0; j < quorumApkUpdatesLength; j++) {
if (apkHistory[quorumNumber][quorumApkUpdatesLength - j - 1].updateBlockNumber <= blockNumber) {
indices[i] = quorumApkUpdatesLength - j - 1;
// Loop backward through apkHistory until we find an entry that preceeds `blockNumber`
for (uint256 j = quorumApkUpdatesLength; j > 0; j--) {
if (apkHistory[quorumNumber][j - 1].updateBlockNumber <= blockNumber) {
indices[i] = uint32(j - 1);
break;
}
}
Expand Down
13 changes: 10 additions & 3 deletions src/BLSSignatureChecker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ contract BLSSignatureChecker is IBLSSignatureChecker {

/**
* RegistryCoordinator owner can either enforce or not that operator stakes are staler
* than the delegation.withdrawalDelayBlocks() window.
* than the delegation.minWithdrawalDelayBlocks() window.
* @param value to toggle staleStakesForbidden
*/
function setStaleStakesForbidden(bool value) external onlyCoordinatorOwner {
Expand Down Expand Up @@ -75,6 +75,9 @@ contract BLSSignatureChecker is IBLSSignatureChecker {
* is correct, i.e., ensure that the stake returned from the specified block number is recent enough and that the stake is either the most recent update
* for the total stake (of the operator) or latest before the referenceBlockNumber.
* @param msgHash is the hash being signed
* @dev NOTE: Be careful to ensure `msgHash` is collision-resistant! This method does not hash
* `msgHash` in any way, so if an attacker is able to pass in an arbitrary value, they may be able
* to tamper with signature verification.
* @param quorumNumbers is the bytes array of quorum numbers that are being signed for
* @param referenceBlockNumber is the block number at which the stake information is being verified
* @param params is the struct containing information on nonsigners, stakes, quorum apks, and the aggregate signature
Expand Down Expand Up @@ -109,7 +112,7 @@ contract BLSSignatureChecker is IBLSSignatureChecker {
"BLSSignatureChecker.checkSignatures: input nonsigner length mismatch"
);

require(referenceBlockNumber <= uint32(block.number), "BLSSignatureChecker.checkSignatures: invalid reference block");
require(referenceBlockNumber < uint32(block.number), "BLSSignatureChecker.checkSignatures: invalid reference block");

// This method needs to calculate the aggregate pubkey for all signing operators across
// all signing quorums. To do that, we can query the aggregate pubkey for each quorum
Expand Down Expand Up @@ -179,8 +182,8 @@ contract BLSSignatureChecker is IBLSSignatureChecker {
* - subtract the stake for each nonsigner to calculate the stake belonging to signers
*/
{
uint256 withdrawalDelayBlocks = delegation.withdrawalDelayBlocks();
bool _staleStakesForbidden = staleStakesForbidden;
uint256 withdrawalDelayBlocks = _staleStakesForbidden ? delegation.minWithdrawalDelayBlocks() : 0;

for (uint256 i = 0; i < quorumNumbers.length; i++) {
// If we're disallowing stale stake updates, check that each quorum's last update block
Expand Down Expand Up @@ -280,4 +283,8 @@ contract BLSSignatureChecker is IBLSSignatureChecker {
PAIRING_EQUALITY_CHECK_GAS
);
}

// storage gap for upgradeability
// slither-disable-next-line shadowing-state
uint256[49] private __GAP;
}
22 changes: 10 additions & 12 deletions src/IndexRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,11 @@ contract IndexRegistry is IndexRegistryStorage {
uint32 blockNumber
) internal view returns (uint32){
uint256 historyLength = _operatorCountHistory[quorumNumber].length;
require(historyLength != 0, "IndexRegistry._operatorCountAtBlockNumber: quorum does not exist");

// Loop backwards through the total operator history
for (uint256 i = 0; i < historyLength; i++) {
uint256 listIndex = (historyLength - 1) - i;
QuorumUpdate memory quorumUpdate = _operatorCountHistory[quorumNumber][listIndex];
// Look for the first update that began before or at `blockNumber`
// Loop backwards through _operatorCountHistory until we find an entry that preceeds `blockNumber`
for (uint256 i = historyLength; i > 0; i--) {
QuorumUpdate memory quorumUpdate = _operatorCountHistory[quorumNumber][i - 1];

if (quorumUpdate.fromBlockNumber <= blockNumber) {
return quorumUpdate.numOperators;
}
Expand All @@ -278,18 +276,18 @@ contract IndexRegistry is IndexRegistryStorage {
uint32 blockNumber
) internal view returns(bytes32) {
uint256 historyLength = _operatorIndexHistory[quorumNumber][operatorIndex].length;
// Loop backward through operatorIndex history
for (uint256 i = 0; i < historyLength; i++) {
uint256 listIndex = (historyLength - 1) - i;
OperatorUpdate memory operatorIndexUpdate = _operatorIndexHistory[quorumNumber][operatorIndex][listIndex];
// Look for the first update that began before or at `blockNumber`

// Loop backward through _operatorIndexHistory until we find an entry that preceeds `blockNumber`
for (uint256 i = historyLength; i > 0; i--) {
OperatorUpdate memory operatorIndexUpdate = _operatorIndexHistory[quorumNumber][operatorIndex][i - 1];

if (operatorIndexUpdate.fromBlockNumber <= blockNumber) {
// Special case: this will be OPERATOR_DOES_NOT_EXIST_ID if this operatorIndex was not used at the block number
return operatorIndexUpdate.operatorId;
}
}

// we should only it this if the operatorIndex was never used before blockNumber
// we should only hit this if the operatorIndex was never used before blockNumber
return OPERATOR_DOES_NOT_EXIST_ID;
}

Expand Down
Loading

0 comments on commit 2809671

Please sign in to comment.