Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 4 additions & 2 deletions mainnet-contracts/script/SetupAccess.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,14 @@ contract SetupAccess is BaseScript {
function _setupPufferProtocolRoles() internal view returns (bytes[] memory) {
bytes[] memory calldatas = new bytes[](3);

bytes4[] memory selectors = new bytes4[](5);
bytes4[] memory selectors = new bytes4[](7);
selectors[0] = PufferProtocol.createPufferModule.selector;
selectors[1] = PufferProtocol.setModuleWeights.selector;
selectors[2] = PufferProtocol.setValidatorLimitPerModule.selector;
selectors[2] = PufferProtocol.setBatchesLimitPerModule.selector;
selectors[3] = PufferProtocol.changeMinimumVTAmount.selector;
selectors[4] = PufferProtocol.setVTPenalty.selector;
selectors[5] = PufferProtocol.setPufferProtocolLogic.selector;
selectors[6] = PufferProtocol.setCurrentNumBatches.selector;

calldatas[0] = abi.encodeWithSelector(
AccessManager.setTargetFunctionRole.selector,
Expand Down
25 changes: 20 additions & 5 deletions mainnet-contracts/src/PufferProtocol.sol
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad
/**
* @dev Restricted to the DAO
*/
function setValidatorLimitPerModule(bytes32 moduleName, uint128 limit) external restricted {
_setValidatorLimitPerModule(moduleName, limit);
function setBatchesLimitPerModule(bytes32 moduleName, uint128 limit) external restricted {
_setBatchesLimitPerModule(moduleName, limit);
}

/**
Expand All @@ -270,6 +270,21 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad
_setPufferProtocolLogic(newPufferProtocolLogic);
}

/**
* @dev Restricted to the DAO
*/
function setCurrentNumBatches(bytes32[] calldata moduleNames, uint128[] calldata newCurrentNumBatches)
external
restricted
{
require(moduleNames.length == newCurrentNumBatches.length, InputArrayLengthMismatch());
ProtocolStorage storage $ = _getPufferProtocolStorage();
for (uint256 i = 0; i < moduleNames.length; i++) {
$.moduleLimits[moduleNames[i]].numberOfRegisteredBatches = newCurrentNumBatches[i];
}
emit CurrentNumBatchesSet(moduleNames, newCurrentNumBatches);
}

/**
* @inheritdoc IPufferProtocol
*/
Expand Down Expand Up @@ -440,9 +455,9 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad
*/
function revertIfPaused() external restricted { }

function _setValidatorLimitPerModule(bytes32 moduleName, uint128 limit) internal {
function _setBatchesLimitPerModule(bytes32 moduleName, uint128 limit) internal {
ProtocolStorage storage $ = _getPufferProtocolStorage();
require($.moduleLimits[moduleName].numberOfRegisteredValidators <= limit, ValidatorLimitForModuleReached());
require($.moduleLimits[moduleName].numberOfRegisteredBatches <= limit, NumBatchesLimitForModuleReached());
emit ValidatorLimitPerModuleChanged($.moduleLimits[moduleName].allowedLimit, limit);
$.moduleLimits[moduleName].allowedLimit = limit;
}
Expand All @@ -468,7 +483,7 @@ contract PufferProtocol is IPufferProtocol, AccessManagedUpgradeable, UUPSUpgrad
$.moduleWeights.push(moduleName);
bytes32 withdrawalCredentials = bytes32(module.getWithdrawalCredentials());
emit NewPufferModuleCreated(address(module), moduleName, withdrawalCredentials);
_setValidatorLimitPerModule(moduleName, 500);
_setBatchesLimitPerModule(moduleName, _DEFAULT_MAX_BATCHES_PER_MODULE);
return address(module);
}

Expand Down
9 changes: 7 additions & 2 deletions mainnet-contracts/src/PufferProtocolBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ abstract contract PufferProtocolBase is PufferProtocolStorage, ProtocolSignature

/**
* @notice Thrown when the new validators tires to register to a module, but the validator limit for that module is already reached
* @dev Signature "0xb75c5781"
* @dev Signature "0x7cb4ca32"
*/
error ValidatorLimitForModuleReached();
error NumBatchesLimitForModuleReached();

/**
* @notice Thrown when the BLS public key is not valid
Expand Down Expand Up @@ -158,6 +158,11 @@ abstract contract PufferProtocolBase is PufferProtocolStorage, ProtocolSignature
*/
uint256 internal constant _32_ETH_GWEI = 32 * 10 ** 9;

/**
* @dev Default maximum number of batches per module
*/
uint128 internal constant _DEFAULT_MAX_BATCHES_PER_MODULE = 500;

IGuardianModule internal immutable _GUARDIAN_MODULE;

ValidatorTicket internal immutable _VALIDATOR_TICKET;
Expand Down
27 changes: 15 additions & 12 deletions mainnet-contracts/src/PufferProtocolLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,12 @@ contract PufferProtocolLogic is PufferProtocolBase, IPufferProtocolLogic {
$.nodeOperatorInfo[msg.sender].validationTime += (msg.value - bondAmountEth);
++$.nodeOperatorInfo[msg.sender].pendingValidatorCount;
++$.pendingValidatorIndices[moduleName];
++$.moduleLimits[moduleName].numberOfRegisteredValidators;
$.moduleLimits[moduleName].numberOfRegisteredBatches += numBatches;
}

emit NumberOfRegisteredValidatorsChanged({
emit NumberOfRegisteredBatchesChanged({
moduleName: moduleName,
newNumberOfRegisteredValidators: $.moduleLimits[moduleName].numberOfRegisteredValidators
numberOfRegisteredBatches: $.moduleLimits[moduleName].numberOfRegisteredBatches
});
emit ValidatorKeyRegistered({
pubKey: data.blsPubKey,
Expand Down Expand Up @@ -283,7 +283,7 @@ contract PufferProtocolLogic is PufferProtocolBase, IPufferProtocolLogic {
// slither-disable-next-line unchecked-transfer
_PUFFER_VAULT.transfer(node, $.validators[moduleName][skippedIndex].bond);

_decreaseNumberOfRegisteredValidators($, moduleName);
_decreaseNumberOfRegisteredBatches($, moduleName, $.validators[moduleName][skippedIndex].numBatches);
unchecked {
++$.nextToBeProvisioned[moduleName];
}
Expand Down Expand Up @@ -585,7 +585,7 @@ contract PufferProtocolLogic is PufferProtocolBase, IPufferProtocolLogic {
bondBurnAmount = _getBondBurnAmount({
validatorInfo: validatorInfo,
validatorBondAmount: bondAmount,
numBatches: validator.numBatches
numBatches: numBatches
});

emit ValidatorExited({
Expand All @@ -597,7 +597,7 @@ contract PufferProtocolLogic is PufferProtocolBase, IPufferProtocolLogic {
});

// Decrease the number of registered validators for that module
_decreaseNumberOfRegisteredValidators($, validatorInfo.moduleName);
_decreaseNumberOfRegisteredBatches($, validatorInfo.moduleName, validator.numBatches);

// Storage VT and the active validator count update for the Node Operator
// nosemgrep basic-arithmetic-underflow
Expand All @@ -611,9 +611,11 @@ contract PufferProtocolLogic is PufferProtocolBase, IPufferProtocolLogic {
return (bondBurnAmount, bondAmount - bondBurnAmount, numBatches);
}

function _decreaseNumberOfRegisteredValidators(ProtocolStorage storage $, bytes32 moduleName) internal {
--$.moduleLimits[moduleName].numberOfRegisteredValidators;
emit NumberOfRegisteredValidatorsChanged(moduleName, $.moduleLimits[moduleName].numberOfRegisteredValidators);
function _decreaseNumberOfRegisteredBatches(ProtocolStorage storage $, bytes32 moduleName, uint128 numBatches)
internal
{
$.moduleLimits[moduleName].numberOfRegisteredBatches -= numBatches;
emit NumberOfRegisteredBatchesChanged(moduleName, $.moduleLimits[moduleName].numberOfRegisteredBatches);
}

function _getBondBurnAmount(
Expand Down Expand Up @@ -648,10 +650,11 @@ contract PufferProtocolLogic is PufferProtocolBase, IPufferProtocolLogic {
require(0 < data.numBatches && data.numBatches < 65, InvalidNumberOfBatches());

// This acts as a validation if the module is existent
// +1 is to validate the current transaction registration
// +numBatches is to validate the current transaction registration
require(
($.moduleLimits[moduleName].numberOfRegisteredValidators + 1) <= $.moduleLimits[moduleName].allowedLimit,
ValidatorLimitForModuleReached()
($.moduleLimits[moduleName].numberOfRegisteredBatches + data.numBatches)
<= $.moduleLimits[moduleName].allowedLimit,
NumBatchesLimitForModuleReached()
);

require(data.blsPubKey.length == _BLS_PUB_KEY_LENGTH, InvalidBLSPubKey());
Expand Down
12 changes: 9 additions & 3 deletions mainnet-contracts/src/interface/IPufferProtocolEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ pragma solidity >=0.8.0 <0.9.0;
*/
interface IPufferProtocolEvents {
/**
* @notice Emitted when the number of active validators changes
* @dev Signature "0xc06afc2b3c88873a9be580de9bbbcc7fea3027ef0c25fd75d5411ed3195abcec"
* @notice Emitted when the number of active batches changes
* @dev Signature "0xe0be9dc31510a09f13dba14d047e637a5bee5976426ec076ebf3aa3884099d5e"
*/
event NumberOfRegisteredValidatorsChanged(bytes32 indexed moduleName, uint256 newNumberOfRegisteredValidators);
event NumberOfRegisteredBatchesChanged(bytes32 indexed moduleName, uint256 numberOfRegisteredBatches);

/**
* @notice Emitted when the validation time is deposited
Expand Down Expand Up @@ -158,4 +158,10 @@ interface IPufferProtocolEvents {
* @dev Signature "0xe271f36954242c619ce9d0f727a7d3b5f4db04666752aaeb20bca6d52098792a"
*/
event PufferProtocolLogicSet(address oldPufferProtocolLogic, address newPufferProtocolLogic);

/**
* @notice Emitted when the current number of batches is set
* @dev Signature "0x4d193bcf314540fd194820a44042b5d498e3f07ab578fcd422f1023a4123f32b"
*/
event CurrentNumBatchesSet(bytes32[] moduleNames, uint128[] newCurrentNumBatches);
}
23 changes: 22 additions & 1 deletion mainnet-contracts/src/interface/IPufferProtocolManagement.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,48 @@ pragma solidity >=0.8.0 <0.9.0;
*/
interface IPufferProtocolManagement {
/**
* @notice Change the minimum amount of VT that can be deposited
* @param newMinimumVTAmount The new minimum amount of VT that can be deposited
* @dev Restricted to the DAO
*/
function changeMinimumVTAmount(uint256 newMinimumVTAmount) external;

/**
* @notice Change the weights of the modules
* @param newModuleWeights The new weights of the modules
* @dev Restricted to the DAO
*/
function setModuleWeights(bytes32[] calldata newModuleWeights) external;

/**
* @notice Change the number of batches that can be registered for a module
* @param moduleName The name of the module
* @param limit The new number of batches that can be registered for a module
* @dev Restricted to the DAO
*/
function setValidatorLimitPerModule(bytes32 moduleName, uint128 limit) external;
function setBatchesLimitPerModule(bytes32 moduleName, uint128 limit) external;

/**
* @notice Change the penalty amount for a module
* @param newPenaltyAmount The new penalty amount for a module
* @dev Restricted to the DAO
*/
function setVTPenalty(uint256 newPenaltyAmount) external;

/**
* @notice Change the PufferProtocolLogic contract
* @param newPufferProtocolLogic The new PufferProtocolLogic contract
* @dev Restricted to the DAO
*/
function setPufferProtocolLogic(address newPufferProtocolLogic) external;

/**
* @notice Set the number of batches that are currently active for a module
* @param moduleNames The names of the modules
* @param newCurrentNumBatches The new number of batches that are currently active for a module
* @dev Restricted to the DAO
* @dev This function should only be called once, after the PufferProtocol contract is upgraded to the Pectra version.
* This is because the limit used to be the number of validators, and now it is the number of batches.
*/
function setCurrentNumBatches(bytes32[] calldata moduleNames, uint128[] calldata newCurrentNumBatches) external;
}
2 changes: 1 addition & 1 deletion mainnet-contracts/src/struct/ProtocolStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,5 @@ struct ProtocolStorage {

struct ModuleLimit {
uint128 allowedLimit;
uint128 numberOfRegisteredValidators;
uint128 numberOfRegisteredBatches;
}
14 changes: 7 additions & 7 deletions mainnet-contracts/test/unit/PufferProtocol.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -181,15 +181,15 @@ contract PufferProtocolTest is UnitTestHelper {

ModuleLimit memory moduleLimit = pufferProtocol.getModuleLimitInformation(PUFFER_MODULE_0);

assertEq(moduleLimit.numberOfRegisteredValidators, 2, "2 active validators");
assertEq(moduleLimit.numberOfRegisteredBatches, 2, "2 active batches");

vm.expectEmit(true, true, true, true);
emit IPufferProtocolEvents.ValidatorSkipped(_getPubKey(bytes32("alice")), 0, PUFFER_MODULE_0);
pufferProtocol.skipProvisioning(PUFFER_MODULE_0, _getGuardianSignaturesForSkipping());

moduleLimit = pufferProtocol.getModuleLimitInformation(PUFFER_MODULE_0);

assertEq(moduleLimit.numberOfRegisteredValidators, 1, "1 active validator");
assertEq(moduleLimit.numberOfRegisteredBatches, 1, "1 active batches");

// This contract should receive pufETH because of the skipProvisioning
assertTrue(pufferVault.balanceOf(address(this)) != 0, "non zero pufETH");
Expand Down Expand Up @@ -221,7 +221,7 @@ contract PufferProtocolTest is UnitTestHelper {
uint256 smoothingCommitment = pufferOracle.getValidatorTicketPrice() * 30;
bytes memory pubKey = _getPubKey(bytes32("charlie"));
ValidatorKeyData memory validatorKeyData = _getMockValidatorKeyData(pubKey, PUFFER_MODULE_0);
vm.expectRevert(PufferProtocolBase.ValidatorLimitForModuleReached.selector);
vm.expectRevert(PufferProtocolBase.NumBatchesLimitForModuleReached.selector);
pufferProtocol.registerValidatorKey{ value: smoothingCommitment }(
validatorKeyData, bytes32("imaginary module"), 0, new bytes[](0), block.timestamp + 1 days
);
Expand Down Expand Up @@ -617,14 +617,14 @@ contract PufferProtocolTest is UnitTestHelper {

vm.expectEmit(true, true, true, true);
emit IPufferProtocolEvents.ValidatorLimitPerModuleChanged(500, 1);
pufferProtocol.setValidatorLimitPerModule(PUFFER_MODULE_0, 1);
pufferProtocol.setBatchesLimitPerModule(PUFFER_MODULE_0, 1);

// Revert if the registration will be over the limit
uint256 smoothingCommitment = pufferOracle.getValidatorTicketPrice();
bytes memory pubKey = _getPubKey(bytes32("bob"));
ValidatorKeyData memory validatorKeyData = _getMockValidatorKeyData(pubKey, PUFFER_MODULE_0);

vm.expectRevert(PufferProtocolBase.ValidatorLimitForModuleReached.selector);
vm.expectRevert(PufferProtocolBase.NumBatchesLimitForModuleReached.selector);
pufferProtocol.registerValidatorKey{ value: (smoothingCommitment + BOND) }(
validatorKeyData, PUFFER_MODULE_0, 0, new bytes[](0), block.timestamp + 1 days
);
Expand Down Expand Up @@ -787,7 +787,7 @@ contract PufferProtocolTest is UnitTestHelper {

vm.stopPrank();
vm.expectEmit(true, true, true, true);
emit IPufferProtocolEvents.NumberOfRegisteredValidatorsChanged(PUFFER_MODULE_0, 0);
emit IPufferProtocolEvents.NumberOfRegisteredBatchesChanged(PUFFER_MODULE_0, 0);
pufferProtocol.skipProvisioning(PUFFER_MODULE_0, _getGuardianSignaturesForSkipping());

assertApproxEqRel(
Expand Down Expand Up @@ -1981,7 +1981,7 @@ contract PufferProtocolTest is UnitTestHelper {
function _createModules() internal {
// Create EIGEN_DA module
pufferProtocol.createPufferModule(EIGEN_DA);
pufferProtocol.setValidatorLimitPerModule(EIGEN_DA, 15);
pufferProtocol.setBatchesLimitPerModule(EIGEN_DA, 15);

// Include the EIGEN_DA in module selection
bytes32[] memory newWeights = new bytes32[](4);
Expand Down