Skip to content

Commit

Permalink
Merge pull request #336 from chainbound/nico/feat/cheaper-unsafe-optin
Browse files Browse the repository at this point in the history
feat(registry): cheaper on-chain batch opt-in (48k gas)
  • Loading branch information
mempirate authored Oct 30, 2024
2 parents 1d8d5bb + 0d6e512 commit 795746d
Show file tree
Hide file tree
Showing 26 changed files with 6,452 additions and 114 deletions.
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

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

0 comments on commit 795746d

Please sign in to comment.