Skip to content
Merged
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
116 changes: 116 additions & 0 deletions contracts-abi/abi/VanillaRegistry.abi
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,19 @@
],
"stateMutability": "view"
},
{
"type": "function",
"name": "removeWhitelistedStakers",
"inputs": [
{
"name": "stakers",
"type": "address[]",
"internalType": "address[]"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "renounceOwnership",
Expand Down Expand Up @@ -633,6 +646,38 @@
"outputs": [],
"stateMutability": "payable"
},
{
"type": "function",
"name": "whitelistStakers",
"inputs": [
{
"name": "stakers",
"type": "address[]",
"internalType": "address[]"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "whitelistedStakers",
"inputs": [
{
"name": "staker",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "whitelisted",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "withdraw",
Expand Down Expand Up @@ -941,6 +986,44 @@
],
"anonymous": false
},
{
"type": "event",
"name": "StakerRemovedFromWhitelist",
"inputs": [
{
"name": "msgSender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "staker",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "StakerWhitelisted",
"inputs": [
{
"name": "msgSender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "staker",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "TotalStakeWithdrawn",
Expand Down Expand Up @@ -1188,6 +1271,17 @@
}
]
},
{
"type": "error",
"name": "SenderIsNotWhitelistedStaker",
"inputs": [
{
"name": "sender",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "SenderIsNotWithdrawalAddress",
Expand Down Expand Up @@ -1250,6 +1344,28 @@
}
]
},
{
"type": "error",
"name": "StakerAlreadyWhitelisted",
"inputs": [
{
"name": "staker",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "StakerNotWhitelisted",
"inputs": [
{
"name": "staker",
"type": "address",
"internalType": "address"
}
]
},
{
"type": "error",
"name": "TransferToRecipientFailed",
Expand Down
365 changes: 364 additions & 1 deletion contracts-abi/clients/VanillaRegistry/VanillaRegistry.go

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions contracts/contracts/interfaces/IVanillaRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ interface IVanillaRegistry {
/// @dev Event emitted when the slashing payout period blocks parameter is set.
event SlashingPayoutPeriodBlocksSet(address indexed msgSender, uint256 newSlashingPayoutPeriodBlocks);

/// @dev Event emitted when a staker is whitelisted.
event StakerWhitelisted(address indexed msgSender, address staker);

/// @dev Event emitted when a staker is removed from the whitelist.
event StakerRemovedFromWhitelist(address indexed msgSender, address staker);

error ValidatorRecordMustExist(bytes valBLSPubKey);
error ValidatorRecordMustNotExist(bytes valBLSPubKey);
error ValidatorCannotBeUnstaking(bytes valBLSPubKey);
Expand All @@ -70,6 +76,9 @@ interface IVanillaRegistry {
error SlashReceiverMustBeSet();
error UnstakePeriodMustBePositive();
error SlashingPayoutPeriodMustBePositive();
error SenderIsNotWhitelistedStaker(address sender);
error StakerAlreadyWhitelisted(address staker);
error StakerNotWhitelisted(address staker);

/// @dev Initializes the contract with the provided parameters.
function initialize(
Expand Down
30 changes: 28 additions & 2 deletions contracts/contracts/validator-registry/VanillaRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ contract VanillaRegistry is IVanillaRegistry, VanillaRegistryStorage,
_;
}

/// @dev Modifier to confirm the sender is whitelisted.
modifier onlyWhitelistedStaker() {
require(whitelistedStakers[msg.sender], IVanillaRegistry.SenderIsNotWhitelistedStaker(msg.sender));
_;
}

/// @dev See https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#initializing_the_implementation_contract
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
Expand Down Expand Up @@ -69,7 +75,7 @@ contract VanillaRegistry is IVanillaRegistry, VanillaRegistryStorage,
* @param blsPubKeys The validator BLS public keys to stake.
*/
function stake(bytes[] calldata blsPubKeys) external payable
onlyValidBLSPubKeys(blsPubKeys) whenNotPaused() {
onlyValidBLSPubKeys(blsPubKeys) onlyWhitelistedStaker() whenNotPaused() {
_stake(blsPubKeys, msg.sender);
}

Expand All @@ -90,7 +96,7 @@ contract VanillaRegistry is IVanillaRegistry, VanillaRegistryStorage,
* @dev A staking entry must already exist for each provided BLS pubkey.
* @param blsPubKeys The BLS public keys to add stake to.
*/
function addStake(bytes[] calldata blsPubKeys) external payable whenNotPaused() {
function addStake(bytes[] calldata blsPubKeys) external payable onlyWhitelistedStaker() whenNotPaused() {
_addStake(blsPubKeys);
}

Expand Down Expand Up @@ -180,6 +186,26 @@ contract VanillaRegistry is IVanillaRegistry, VanillaRegistryStorage,
FeePayout.transferToRecipient(slashingFundsTracker);
}

/// @dev Enables the owner to whitelist stakers.
function whitelistStakers(address[] calldata stakers) external onlyOwner {
uint256 len = stakers.length;
for (uint256 i = 0; i < len; ++i) {
require(!whitelistedStakers[stakers[i]], IVanillaRegistry.StakerAlreadyWhitelisted(stakers[i]));
whitelistedStakers[stakers[i]] = true;
emit StakerWhitelisted(msg.sender, stakers[i]);
}
}

/// @dev Enables the owner to remove stakers from the whitelist.
function removeWhitelistedStakers(address[] calldata stakers) external onlyOwner {
uint256 len = stakers.length;
for (uint256 i = 0; i < len; ++i) {
require(whitelistedStakers[stakers[i]], IVanillaRegistry.StakerNotWhitelisted(stakers[i]));
whitelistedStakers[stakers[i]] = false;
emit StakerRemovedFromWhitelist(msg.sender, stakers[i]);
}
}

/// @dev Returns true if a validator is considered "opted-in" to mev-commit via this registry.
function isValidatorOptedIn(bytes calldata valBLSPubKey) external view returns (bool) {
return _isValidatorOptedIn(valBLSPubKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ contract VanillaRegistryStorage {
/// @dev Mapping of withdrawal addresses to claimable ETH that was force withdrawn by the owner.
mapping(address withdrawalAddress => uint256 amountToClaim) public forceWithdrawnFunds;

/// @dev Mapping of staker addresses to whether they are whitelisted.
mapping(address staker => bool whitelisted) public whitelistedStakers;

/// @dev See https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps
uint256[48] private __gap;
}
Loading
Loading