Skip to content

Commit

Permalink
feat: Make CSVerifier pausable
Browse files Browse the repository at this point in the history
  • Loading branch information
dgusakov committed Jan 9, 2025
1 parent 72eace1 commit 0966118
Show file tree
Hide file tree
Showing 12 changed files with 304 additions and 26 deletions.
11 changes: 9 additions & 2 deletions script/DeployBase.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ abstract contract DeployBase is Script {
),
pivotSlot: Slot.wrap(
uint64(config.verifierSupportedEpoch * config.slotsPerEpoch)
)
),
admin: deployer
});

accounting.initialize({
Expand Down Expand Up @@ -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);

accounting.grantRole(
accounting.SET_BOND_CURVE_ROLE(),
config.setResetBondCurveAddress
Expand Down Expand Up @@ -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);

accounting.grantRole(
accounting.DEFAULT_ADMIN_ROLE(),
config.aragonAgent
Expand Down Expand Up @@ -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
Expand Down
10 changes: 7 additions & 3 deletions script/DeployCSVerifierElectra.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct Config {
Slot firstSupportedSlot;
Slot pivotSlot;
uint64 slotsPerEpoch;
address admin;
}

// Check the constants below via `yarn run gindex`.
Expand Down Expand Up @@ -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));
}
Expand All @@ -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
});
}
}
Expand All @@ -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
Expand Up @@ -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();
Expand Down
27 changes: 23 additions & 4 deletions src/CSVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
12 changes: 12 additions & 0 deletions src/interfaces/ICSVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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.
Expand Down
Loading

0 comments on commit 0966118

Please sign in to comment.