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: Make CSVerifier pausable #379

Merged
merged 4 commits into from
Jan 13, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: Make CSVerifier pausable
dgusakov committed Jan 9, 2025
commit 0966118f0a1136323363f33fdfb0ac1716e1842d
11 changes: 9 additions & 2 deletions script/DeployBase.s.sol
Original file line number Diff line number Diff line change
@@ -189,7 +189,8 @@ abstract contract DeployBase is Script {
),
pivotSlot: Slot.wrap(
uint64(config.verifierSupportedEpoch * config.slotsPerEpoch)
)
),
admin: deployer
});

accounting.initialize({
@@ -264,6 +265,8 @@ abstract contract DeployBase is Script {
csm.grantRole(csm.PAUSE_ROLE(), gateSeal);
oracle.grantRole(oracle.PAUSE_ROLE(), gateSeal);
accounting.grantRole(accounting.PAUSE_ROLE(), gateSeal);
verifier.grantRole(accounting.PAUSE_ROLE(), gateSeal);
dgusakov marked this conversation as resolved.
Show resolved Hide resolved

accounting.grantRole(
accounting.SET_BOND_CURVE_ROLE(),
config.setResetBondCurveAddress
@@ -291,6 +294,9 @@ abstract contract DeployBase is Script {
csm.grantRole(csm.DEFAULT_ADMIN_ROLE(), config.aragonAgent);
csm.revokeRole(csm.DEFAULT_ADMIN_ROLE(), deployer);

verifier.grantRole(csm.DEFAULT_ADMIN_ROLE(), config.aragonAgent);
verifier.revokeRole(csm.DEFAULT_ADMIN_ROLE(), deployer);
dgusakov marked this conversation as resolved.
Show resolved Hide resolved

accounting.grantRole(
accounting.DEFAULT_ADMIN_ROLE(),
config.aragonAgent
@@ -354,10 +360,11 @@ abstract contract DeployBase is Script {
IGateSealFactory gateSealFactory = IGateSealFactory(
config.gateSealFactory
);
address[] memory sealables = new address[](3);
address[] memory sealables = new address[](4);
sealables[0] = address(csm);
sealables[1] = address(accounting);
sealables[2] = address(oracle);
sealables[3] = address(verifier);

address committee = config.sealingCommittee == address(0)
? deployer
10 changes: 7 additions & 3 deletions script/DeployCSVerifierElectra.s.sol
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ struct Config {
Slot firstSupportedSlot;
Slot pivotSlot;
uint64 slotsPerEpoch;
address admin;
}

// Check the constants below via `yarn run gindex`.
@@ -63,7 +64,8 @@ abstract contract DeployCSVerifier is Script {
gIHistoricalSummariesPrev: config.gIHistoricalSummariesPrev,
gIHistoricalSummariesCurr: config.gIHistoricalSummariesCurr,
firstSupportedSlot: config.firstSupportedSlot,
pivotSlot: config.pivotSlot
pivotSlot: config.pivotSlot,
admin: config.admin
});
console.log("CSVerifier deployed at:", address(verifier));
}
@@ -82,7 +84,8 @@ contract DeployCSVerifierHolesky is DeployCSVerifier {
gIHistoricalSummariesPrev: HISTORICAL_SUMMARIES_DENEB,
gIHistoricalSummariesCurr: HISTORICAL_SUMMARIES_ELECTRA,
firstSupportedSlot: Slot.wrap(950272), // 269_568 * 32, @see https://github.com/eth-clients/mainnet/blob/main/metadata/config.yaml#L52
pivotSlot: Slot.wrap(0) // TODO: Update with Electra slot.
pivotSlot: Slot.wrap(0), // TODO: Update with Electra slot.
admin: 0xE92329EC7ddB11D25e25b3c21eeBf11f15eB325d // Aragon Agent
});
}
}
@@ -100,7 +103,8 @@ contract DeployCSVerifierMainnet is DeployCSVerifier {
gIHistoricalSummariesPrev: HISTORICAL_SUMMARIES_DENEB,
gIHistoricalSummariesCurr: HISTORICAL_SUMMARIES_ELECTRA,
firstSupportedSlot: Slot.wrap(8626176), // 29_696 * 32, @see https://github.com/eth-clients/holesky/blob/main/metadata/config.yaml#L38
pivotSlot: Slot.wrap(0) // TODO: Update with Electra slot.
pivotSlot: Slot.wrap(0), // TODO: Update with Electra slot.
admin: 0x3e40D73EB977Dc6a537aF587D48316feE66E9C8c // Aragon Agent
});
}
}
3 changes: 2 additions & 1 deletion script/DeployImplementationsBase.s.sol
Original file line number Diff line number Diff line change
@@ -80,7 +80,8 @@ abstract contract DeployImplementationsBase is DeployBase {
),
pivotSlot: Slot.wrap(
uint64(config.verifierSupportedEpoch * config.slotsPerEpoch)
)
),
admin: msg.sender
});

JsonObj memory deployJson = Json.newObj();
27 changes: 23 additions & 4 deletions src/CSVerifier.sol
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@ pragma solidity 0.8.24;

import { ICSVerifier } from "./interfaces/ICSVerifier.sol";
import { ICSModule } from "./interfaces/ICSModule.sol";
import { AccessControlEnumerable } from "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol";
import { PausableUntil } from "./lib/utils/PausableUntil.sol";

import { BeaconBlockHeader, Slot, Validator, Withdrawal } from "./lib/Types.sol";
import { GIndex } from "./lib/GIndex.sol";
@@ -22,13 +24,16 @@ function gweiToWei(uint64 amount) pure returns (uint256) {
return uint256(amount) * 1 gwei;
}

contract CSVerifier is ICSVerifier {
contract CSVerifier is ICSVerifier, AccessControlEnumerable, PausableUntil {
using { amountWei } for Withdrawal;

using SSZ for BeaconBlockHeader;
using SSZ for Withdrawal;
using SSZ for Validator;

bytes32 public constant PAUSE_ROLE = keccak256("PAUSE_ROLE");
bytes32 public constant RESUME_ROLE = keccak256("RESUME_ROLE");

// See `BEACON_ROOTS_ADDRESS` constant in the EIP-4788.
address public constant BEACON_ROOTS =
0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02;
@@ -77,10 +82,12 @@ contract CSVerifier is ICSVerifier {
GIndex gIHistoricalSummariesPrev,
GIndex gIHistoricalSummariesCurr,
Slot firstSupportedSlot,
Slot pivotSlot
Slot pivotSlot,
address admin
) {
if (withdrawalAddress == address(0)) revert ZeroWithdrawalAddress();
if (module == address(0)) revert ZeroModuleAddress();
if (admin == address(0)) revert ZeroAdminAddress();

if (slotsPerEpoch == 0) revert InvalidChainConfig();
if (firstSupportedSlot > pivotSlot) revert InvalidPivotSlot();
@@ -101,6 +108,18 @@ contract CSVerifier is ICSVerifier {

FIRST_SUPPORTED_SLOT = firstSupportedSlot;
PIVOT_SLOT = pivotSlot;

_grantRole(DEFAULT_ADMIN_ROLE, admin);
}

/// @inheritdoc ICSVerifier
function resume() external onlyRole(RESUME_ROLE) {
_resume();
}

/// @inheritdoc ICSVerifier
function pauseFor(uint256 duration) external onlyRole(PAUSE_ROLE) {
_pauseFor(duration);
}

/// @inheritdoc ICSVerifier
@@ -109,7 +128,7 @@ contract CSVerifier is ICSVerifier {
WithdrawalWitness calldata witness,
uint256 nodeOperatorId,
uint256 keyIndex
) external {
) external whenResumed {
if (beaconBlock.header.slot < FIRST_SUPPORTED_SLOT) {
revert UnsupportedSlot(beaconBlock.header.slot);
}
@@ -151,7 +170,7 @@ contract CSVerifier is ICSVerifier {
WithdrawalWitness calldata witness,
uint256 nodeOperatorId,
uint256 keyIndex
) external {
) external whenResumed {
if (beaconBlock.header.slot < FIRST_SUPPORTED_SLOT) {
revert UnsupportedSlot(beaconBlock.header.slot);
}
12 changes: 12 additions & 0 deletions src/interfaces/ICSVerifier.sol
Original file line number Diff line number Diff line change
@@ -61,8 +61,13 @@ interface ICSVerifier {
error UnsupportedSlot(Slot slot);
error ZeroModuleAddress();
error ZeroWithdrawalAddress();
error ZeroAdminAddress();
error InvalidPivotSlot();

function PAUSE_ROLE() external view returns (bytes32);

function RESUME_ROLE() external view returns (bytes32);

function BEACON_ROOTS() external view returns (address);

function SLOTS_PER_EPOCH() external view returns (uint64);
@@ -87,6 +92,13 @@ interface ICSVerifier {

function MODULE() external view returns (ICSModule);

/// @notice Pause write methods calls for `duration` seconds
/// @param duration Duration of the pause in seconds
function pauseFor(uint256 duration) external;

/// @notice Resume write methods calls
function resume() external;

/// @notice Verify withdrawal proof and report withdrawal to the module for valid proofs
/// @param beaconBlock Beacon block header
/// @param witness Withdrawal witness against the `beaconBlock`'s state root.
Loading