Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(registry): cheaper on-chain batch opt-in (48k gas) #336

Merged
merged 12 commits into from
Oct 30, 2024
2 changes: 1 addition & 1 deletion bolt-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The Bolt CLI is a collection of command-line tools for interacting with Bolt pro
Prerequisites:

- [Rust toolchain][rust]
- [Protoc][protoc]
- [Protoc][protoc] (as well as `libprotobuf-dev` for some Linux distributions)

Once you have the necessary prerequisites, you can build the binary in the following way:

Expand Down
33 changes: 20 additions & 13 deletions bolt-contracts/.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,25 @@ BoltChallengerTest:testProveTransactionInclusion() (gas: 176543)
BoltChallengerTest:testResolveChallengeFullDefenseSingleTx() (gas: 562694)
BoltChallengerTest:testResolveChallengeFullDefenseStackedTxs() (gas: 939716)
BoltChallengerTest:testResolveExpiredChallenge() (gas: 426457)
BoltManagerEigenLayerTest:testDeregisterOperatorFromAVS() (gas: 755578)
BoltManagerEigenLayerTest:testGetOperatorStake() (gas: 919551)
BoltManagerEigenLayerTest:testNonExistentProposerStatus() (gas: 901546)
BoltManagerEigenLayerTest:testProposerStatus() (gas: 928359)
BoltManagerEigenLayerTest:testProposersLookaheadStatus() (gas: 2221042)
BoltManagerSymbioticTest:testGetNonExistentProposerStatus() (gas: 1168685)
BoltManagerSymbioticTest:testGetProposerStatus() (gas: 1415457)
BoltManagerSymbioticTest:testProposersLookaheadStatus() (gas: 2488651)
BoltManagerSymbioticTest:testReadOperatorStake() (gas: 1448345)
BoltValidatorsTest:testUnsafeRegistration() (gas: 149361)
BoltValidatorsTest:testUnsafeRegistrationFailsIfAlreadyRegistered() (gas: 148862)
BoltValidatorsTest:testUnsafeRegistrationInvalidOperator() (gas: 22820)
BoltValidatorsTest:testUnsafeRegistrationWhenNotAllowed() (gas: 33183)
BoltManagerEigenLayerTest:testDeregisterOperatorFromAVS() (gas: 757038)
BoltManagerEigenLayerTest:testGetOperatorStake() (gas: 916622)
BoltManagerEigenLayerTest:testNonExistentProposerStatus() (gas: 902889)
BoltManagerEigenLayerTest:testProposerStatus() (gas: 927230)
BoltManagerEigenLayerTest:testProposersLookaheadStatus() (gas: 2197665)
BoltManagerSymbioticTest:testGetNonExistentProposerStatus() (gas: 1309103)
BoltManagerSymbioticTest:testGetProposerStatus() (gas: 1556603)
BoltManagerSymbioticTest:testProposersLookaheadStatus() (gas: 2632992)
BoltManagerSymbioticTest:testReadOperatorStake() (gas: 1590527)
BoltValidatorsTest:testUnsafeBatchRegistrationGasUsage() (gas: 29088733)
BoltValidatorsTest:testUnsafeRegistration() (gas: 138036)
BoltValidatorsTest:testUnsafeRegistrationFailsIfAlreadyRegistered() (gas: 135421)
BoltValidatorsTest:testUnsafeRegistrationInvalidOperator() (gas: 17352)
BoltValidatorsTest:testUnsafeRegistrationWhenNotAllowed() (gas: 12330)
BoltValidatorsV2Test:testReadRegisteredValidatorsV2() (gas: 8051)
BoltValidatorsV2Test:testUnauthorizedController() (gas: 3613)
BoltValidatorsV2Test:testUnsafeBatchRegistrationV2() (gas: 29122477)
BoltValidatorsV2Test:testUnsafeRegistrationInvalidOperatorV2() (gas: 10332)
BoltValidatorsV2Test:testUnsafeRegistrationV2() (gas: 215472)
BoltValidatorsV2Test:testUpdateMaxGasLimitV2() (gas: 4434)
TransactionDecoderTest:testDecodeAllTestCases() (gas: 0)
TransactionDecoderTest:testDecodeGasUsage() (gas: 53281)
12 changes: 6 additions & 6 deletions bolt-contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ The values of these parameters can also be found in [`parameters.json`](./config

## Validator Registration: `BoltValidators`

The [`BoltValidators`](./src/contracts/BoltValidatorsV1.sol) contract is the only point of entry for
The [`BoltValidators`](./src/contracts/BoltValidatorsV2.sol) contract is the only point of entry for
validators to signal their intent to participate in Bolt Protocol and authenticate with their BLS private key.

The registration process includes the following steps:
Expand All @@ -76,7 +76,7 @@ will allow us to test the registration flow in a controlled environment.

## Bolt Network Entrypoint: `BoltManager`

The [`BoltManager`](./src/contracts/BoltManagerV1.sol) contract is a crucial component of Bolt that
The [`BoltManager`](./src/contracts/BoltManagerV2.sol) contract is a crucial component of Bolt that
integrates with restaking ecosystems Symbiotic and Eigenlayer. It manages the registration and
coordination of validators, operators, and vaults within the Bolt network.

Expand Down Expand Up @@ -156,10 +156,10 @@ request is valid according to Bolt Protocol rules. -->
| Name | Address | Notes |
| ---------------------- | -------------------- | ----------------------- |
| [`BoltParametersV1`](./src/contracts/BoltParametersV1.sol) | [0x20d1cf3A5BD5928dB3118b2CfEF54FDF9fda5c12](https://holesky.etherscan.io/address/0x20d1cf3A5BD5928dB3118b2CfEF54FDF9fda5c12) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |
| [`BoltValidatorsV1`](./src/contracts/BoltValidatorsV1.sol) | [0x47D2DC1DE1eFEFA5e6944402f2eda3981D36a9c8](https://holesky.etherscan.io/address/0x47D2DC1DE1eFEFA5e6944402f2eda3981D36a9c8) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |
| [`BoltManagerV1`](./src/contracts/BoltManagerV1.sol) | [0x440202829b493F9FF43E730EB5e8379EEa3678CF](https://holesky.etherscan.io/address/0x440202829b493F9FF43E730EB5e8379EEa3678CF) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |
| [`BoltEigenLayerMiddlewareV1`](./src/contracts/BoltEigenLayerMiddlewareV1.sol) | [0xa632a3e652110Bb2901D5cE390685E6a9838Ca04](https://holesky.etherscan.io/address/0xa632a3e652110Bb2901D5cE390685E6a9838Ca04) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |
| [`BoltSymbioticMiddlewareV1`](./src/contracts/BoltSymbioticMiddlewareV1.sol) | [0x04f40d9CaE475E5BaA462acE53E5c58A0DD8D8e8](https://holesky.etherscan.io/address/0x04f40d9CaE475E5BaA462acE53E5c58A0DD8D8e8) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |
| [`BoltValidatorsV2`](./src/contracts/BoltValidatorsV2.sol) | [0x47D2DC1DE1eFEFA5e6944402f2eda3981D36a9c8](https://holesky.etherscan.io/address/0x47D2DC1DE1eFEFA5e6944402f2eda3981D36a9c8) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |
| [`BoltManagerV2`](./src/contracts/BoltManagerV2.sol) | [0x440202829b493F9FF43E730EB5e8379EEa3678CF](https://holesky.etherscan.io/address/0x440202829b493F9FF43E730EB5e8379EEa3678CF) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |
| [`BoltEigenLayerMiddlewareV2`](./src/contracts/BoltEigenLayerMiddlewareV2.sol) | [0xa632a3e652110Bb2901D5cE390685E6a9838Ca04](https://holesky.etherscan.io/address/0xa632a3e652110Bb2901D5cE390685E6a9838Ca04) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |
| [`BoltSymbioticMiddlewareV2`](./src/contracts/BoltSymbioticMiddlewareV2.sol) | [0x04f40d9CaE475E5BaA462acE53E5c58A0DD8D8e8](https://holesky.etherscan.io/address/0x04f40d9CaE475E5BaA462acE53E5c58A0DD8D8e8) | Proxy: [`ERC1967Proxy@5.0.0`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v5.0/contracts/proxy/ERC1967/ERC1967Proxy.sol) |

## Testing

Expand Down
53 changes: 53 additions & 0 deletions bolt-contracts/script/holesky/admin/Upgrade.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ import {Upgrades, Options} from "@openzeppelin-foundry-upgrades/src/Upgrades.sol
import {BoltParametersV1} from "../../../src/contracts/BoltParametersV1.sol";
import {BoltValidatorsV1} from "../../../src/contracts/BoltValidatorsV1.sol";
import {BoltManagerV1} from "../../../src/contracts/BoltManagerV1.sol";
import {BoltManagerV2} from "../../../src/contracts/BoltManagerV2.sol";
import {BoltEigenLayerMiddlewareV1} from "../../../src/contracts/BoltEigenLayerMiddlewareV1.sol";
import {BoltEigenLayerMiddlewareV2} from "../../../src/contracts/BoltEigenLayerMiddlewareV2.sol";
import {BoltSymbioticMiddlewareV1} from "../../../src/contracts/BoltSymbioticMiddlewareV1.sol";
import {BoltSymbioticMiddlewareV2} from "../../../src/contracts/BoltSymbioticMiddlewareV2.sol";
import {BoltValidatorsV1} from "../../../src/contracts/BoltValidatorsV1.sol";
import {BoltValidatorsV2} from "../../../src/contracts/BoltValidatorsV2.sol";
import {BoltConfig} from "../../../src/lib/Config.sol";

contract UpgradeBolt is Script {
struct Deployments {
address boltManager;
address boltParameters;
address boltValidators;
address symbioticNetwork;
address symbioticOperatorRegistry;
address symbioticOperatorNetOptIn;
Expand Down Expand Up @@ -103,6 +107,54 @@ contract UpgradeBolt is Script {
console.log("BoltSymbioticMiddleware proxy upgraded from %s to %s", opts.referenceContract, upgradeTo);
}

function upgradeBoltValidators() public {
address admin = msg.sender;
console.log("Upgrading BoltValidators with admin", admin);
// TODO: Validate upgrades with Upgrades.validateUpgrade
thedevbirb marked this conversation as resolved.
Show resolved Hide resolved

Options memory opts;
opts.unsafeSkipAllChecks = true;
opts.referenceContract = "BoltValidatorsV1.sol";

string memory upgradeTo = "BoltValidatorsV2.sol";

Deployments memory deployments = _readDeployments();

bytes memory initBoltValidators =
abi.encodeCall(BoltValidatorsV2.initializeV2, (admin, deployments.boltParameters));

vm.startBroadcast(admin);

Upgrades.upgradeProxy(deployments.boltValidators, upgradeTo, initBoltValidators, opts);

vm.stopBroadcast();

console.log("BoltValidators proxy upgraded from %s to %s", opts.referenceContract, upgradeTo);
}

function upgradeBoltManager() public {
address admin = msg.sender;
console.log("Upgrading BoltManager with admin", admin);
// TODO: Validate upgrades with Upgrades.validateUpgrade

Options memory opts;
opts.unsafeSkipAllChecks = true;
opts.referenceContract = "BoltManagerV1.sol";
string memory upgradeTo = "BoltManagerV2.sol";

Deployments memory deployments = _readDeployments();
bytes memory initManager =
abi.encodeCall(BoltManagerV2.initializeV2, (admin, deployments.boltParameters, deployments.boltValidators));

vm.startBroadcast(admin);

Upgrades.upgradeProxy(deployments.boltManager, upgradeTo, initManager, opts);

vm.stopBroadcast();

console.log("BoltManager proxy upgraded from %s to %s", opts.referenceContract, upgradeTo);
}

function _readDeployments() public view returns (Deployments memory) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/config/holesky/deployments.json");
Expand All @@ -111,6 +163,7 @@ contract UpgradeBolt is Script {
return Deployments({
boltParameters: vm.parseJsonAddress(json, ".bolt.parameters"),
boltManager: vm.parseJsonAddress(json, ".bolt.manager"),
boltValidators: vm.parseJsonAddress(json, ".bolt.validators"),
symbioticNetwork: vm.parseJsonAddress(json, ".symbiotic.network"),
symbioticOperatorRegistry: vm.parseJsonAddress(json, ".symbiotic.operatorRegistry"),
symbioticOperatorNetOptIn: vm.parseJsonAddress(json, ".symbiotic.networkOptInService"),
Expand Down
4 changes: 2 additions & 2 deletions bolt-contracts/script/holesky/admin/helpers/RegisterAVS.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ pragma solidity 0.8.25;

import {Script, console} from "forge-std/Script.sol";

import {BoltEigenLayerMiddlewareV1} from "../../../../src/contracts/BoltEigenLayerMiddlewareV1.sol";
import {BoltEigenLayerMiddlewareV2} from "../../../../src/contracts/BoltEigenLayerMiddlewareV2.sol";

contract RegisterAVS is Script {
function run() public {
address admin = msg.sender;
console.log("Running with admin address:", admin);

BoltEigenLayerMiddlewareV1 middleware = BoltEigenLayerMiddlewareV1(readMiddleware());
BoltEigenLayerMiddlewareV2 middleware = BoltEigenLayerMiddlewareV2(readMiddleware());

string memory avsURI = "https://boltprotocol.xyz/avs.json";
console.log("Setting AVS metadata URI to:", avsURI);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import {Script, console} from "forge-std/Script.sol";
import {INetworkRegistry} from "@symbiotic/interfaces/INetworkRegistry.sol";
import {INetworkMiddlewareService} from "@symbiotic/interfaces/service/INetworkMiddlewareService.sol";

import {BoltSymbioticMiddlewareV1} from "../../../../src/contracts/BoltSymbioticMiddlewareV1.sol";
import {BoltSymbioticMiddlewareV2} from "../../../../src/contracts/BoltSymbioticMiddlewareV2.sol";

contract UpdateSupportedVaults is Script {
function run() public {
BoltSymbioticMiddlewareV1 middleware = _readSymbioticMiddleware();
BoltSymbioticMiddlewareV2 middleware = _readSymbioticMiddleware();

address[] memory whitelisted = middleware.getWhitelistedVaults();
address[] memory toWhitelist = _readVaultsToWhitelist();
Expand Down Expand Up @@ -64,11 +64,11 @@ contract UpdateSupportedVaults is Script {
return vm.parseJsonAddressArray(json, ".symbiotic.supportedVaults");
}

function _readSymbioticMiddleware() public view returns (BoltSymbioticMiddlewareV1) {
function _readSymbioticMiddleware() public view returns (BoltSymbioticMiddlewareV2) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/config/holesky/deployments.json");
string memory json = vm.readFile(path);

return BoltSymbioticMiddlewareV1(vm.parseJsonAddress(json, ".symbiotic.middleware"));
return BoltSymbioticMiddlewareV2(vm.parseJsonAddress(json, ".symbiotic.middleware"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {IStrategyManager} from "@eigenlayer/src/contracts/interfaces/IStrategyMa
import {IStrategy, IERC20} from "@eigenlayer/src/contracts/interfaces/IStrategy.sol";
import {ISignatureUtils} from "@eigenlayer/src/contracts/interfaces/ISignatureUtils.sol";

import {BoltEigenLayerMiddlewareV1} from "../../../src/contracts/BoltEigenLayerMiddlewareV1.sol";
import {BoltEigenLayerMiddlewareV2} from "../../../src/contracts/BoltEigenLayerMiddlewareV2.sol";
import {IBoltMiddlewareV1} from "../../../src/interfaces/IBoltMiddlewareV1.sol";
import {IBoltManagerV1} from "../../../src/interfaces/IBoltManagerV1.sol";
import {IBoltManagerV2} from "../../../src/interfaces/IBoltManagerV2.sol";

contract RegisterEigenLayerOperator is Script {
struct OperatorConfig {
Expand Down Expand Up @@ -43,7 +43,7 @@ contract RegisterEigenLayerOperator is Script {
uint256 operatorSk = vm.envUint("OPERATOR_SK");
address operator = vm.addr(operatorSk);

BoltEigenLayerMiddlewareV1 middleware = _readMiddleware();
BoltEigenLayerMiddlewareV2 middleware = _readMiddleware();
IAVSDirectory avsDirectory = _readAvsDirectory();
OperatorConfig memory config = _readConfig("config/holesky/operators/eigenlayer/registerIntoBoltAVS.json");

Expand Down Expand Up @@ -76,12 +76,12 @@ contract RegisterEigenLayerOperator is Script {
address operatorAddress = vm.envAddress("OPERATOR_ADDRESS");
console.log("Checking operator registration for address", operatorAddress);

IBoltManagerV1 boltManager = _readBoltManager();
IBoltManagerV2 boltManager = _readBoltManager();
bool isRegistered = boltManager.isOperator(operatorAddress);
console.log("Operator is registered:", isRegistered);
require(isRegistered, "Operator is not registered");

BoltEigenLayerMiddlewareV1 middleware = _readMiddleware();
BoltEigenLayerMiddlewareV2 middleware = _readMiddleware();
(address[] memory tokens, uint256[] memory amounts) = middleware.getOperatorCollaterals(operatorAddress);

for (uint256 i; i < tokens.length; ++i) {
Expand All @@ -91,12 +91,12 @@ contract RegisterEigenLayerOperator is Script {
}
}

function _readMiddleware() public view returns (BoltEigenLayerMiddlewareV1) {
function _readMiddleware() public view returns (BoltEigenLayerMiddlewareV2) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/config/holesky/deployments.json");
string memory json = vm.readFile(path);

return BoltEigenLayerMiddlewareV1(vm.parseJsonAddress(json, ".eigenLayer.middleware"));
return BoltEigenLayerMiddlewareV2(vm.parseJsonAddress(json, ".eigenLayer.middleware"));
}

function _readAvsDirectory() public view returns (IAVSDirectory) {
Expand All @@ -122,11 +122,11 @@ contract RegisterEigenLayerOperator is Script {
return IStrategyManager(vm.parseJsonAddress(json, ".eigenLayer.strategyManager"));
}

function _readBoltManager() public view returns (IBoltManagerV1) {
function _readBoltManager() public view returns (IBoltManagerV2) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/config/holesky/deployments.json");
string memory json = vm.readFile(path);
return IBoltManagerV1(vm.parseJsonAddress(json, ".bolt.manager"));
return IBoltManagerV2(vm.parseJsonAddress(json, ".bolt.manager"));
}

function _readConfig(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ pragma solidity 0.8.25;

import {Script, console} from "forge-std/Script.sol";

import {BoltSymbioticMiddlewareV1} from "../../../src/contracts/BoltSymbioticMiddlewareV1.sol";
import {IBoltManagerV1} from "../../../src/interfaces/IBoltManagerV1.sol";
import {BoltSymbioticMiddlewareV2} from "../../../src/contracts/BoltSymbioticMiddlewareV2.sol";
import {IBoltManagerV2} from "../../../src/interfaces/IBoltManagerV2.sol";

import {IOptInService} from "@symbiotic/interfaces/service/IOptInService.sol";
import {IVault} from "@symbiotic/interfaces/vault/IVault.sol";

contract RegisterSymbioticOperator is Script {
struct Config {
BoltSymbioticMiddlewareV1 symbioticMiddleware;
BoltSymbioticMiddlewareV2 symbioticMiddleware;
IOptInService symbioticNetworkOptInService;
address symbioticNetwork;
}
Expand Down Expand Up @@ -54,7 +54,7 @@ contract RegisterSymbioticOperator is Script {
address operatorAddress = vm.envAddress("OPERATOR_ADDRESS");
console.log("Checking operator registration for address", operatorAddress);

IBoltManagerV1 boltManager = _readBoltManager();
IBoltManagerV2 boltManager = _readBoltManager();
bool isRegistered = boltManager.isOperator(operatorAddress);

console.log("Operator is registered:", isRegistered);
Expand All @@ -68,15 +68,15 @@ contract RegisterSymbioticOperator is Script {

return Config({
symbioticNetwork: vm.parseJsonAddress(json, ".symbiotic.network"),
symbioticMiddleware: BoltSymbioticMiddlewareV1(vm.parseJsonAddress(json, ".symbiotic.middleware")),
symbioticMiddleware: BoltSymbioticMiddlewareV2(vm.parseJsonAddress(json, ".symbiotic.middleware")),
symbioticNetworkOptInService: IOptInService(vm.parseJsonAddress(json, ".symbiotic.networkOptInService"))
});
}

function _readBoltManager() public view returns (IBoltManagerV1) {
function _readBoltManager() public view returns (IBoltManagerV2) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/config/holesky/deployments.json");
string memory json = vm.readFile(path);
return IBoltManagerV1(vm.parseJsonAddress(json, ".bolt.manager"));
return IBoltManagerV2(vm.parseJsonAddress(json, ".bolt.manager"));
}
}
Loading
Loading