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

rought draft: BRING YOUR OWN DSM (for permissiones staking vaults) [very very WIP] #911

Closed
wants to merge 2 commits into from
Closed
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
41 changes: 40 additions & 1 deletion contracts/0.8.25/lib/DepositLogistics.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ pragma solidity 0.8.25;

import { Memory } from "../lib/Memory.sol";
import { IDepositContract } from "../interfaces/IDepositContract.sol";
import {ECDSA} from "contracts/common/lib/ECDSA.sol";

/**
* @title DepositLogistics
* @notice Library for handling Beacon Chain validator deposits
* @dev Provides functionality to process multiple validator deposits to the Beacon Chain deposit contract
*/
library DepositLogistics {
struct Signature {
bytes32 r;
bytes32 vs;
}

/**
* @notice Byte length of the BLS12-381 public key (a.k.a. validator public key)
*/
Expand All @@ -28,6 +34,11 @@ library DepositLogistics {
*/
uint256 internal constant AMOUNT_LENGTH = 8;

/**
* @notice Domain separator for the security signature
*/
bytes32 internal constant GUARDIAN_SIGNATURE_PREFIX = keccak256(abi.encodePacked("GuardianSignaturePrefix"));

/**
* @notice Error thrown when the number of deposits is zero
*/
Expand All @@ -48,6 +59,11 @@ library DepositLogistics {
*/
error AmountsLengthMismatch(uint256 actual, uint256 expected);

/**
* @notice Error thrown when the guardian signature does not match the expected guardian
*/
error InvalidGuardianSignature();

/**
* @notice Processes multiple validator deposits to the Beacon Chain deposit contract
* @param _depositContract The deposit contract interface
Expand All @@ -63,7 +79,9 @@ library DepositLogistics {
bytes memory _creds,
bytes memory _pubkeys,
bytes memory _sigs,
bytes memory _amounts
bytes memory _amounts,
Signature memory _guardianSignature,
address _guardian
) internal {
if (_deposits == 0) revert ZeroDeposits();
if (_pubkeys.length != PUBKEY_LENGTH * _deposits) revert PubkeysLengthMismatch(_pubkeys.length, PUBKEY_LENGTH * _deposits);
Expand All @@ -75,6 +93,9 @@ library DepositLogistics {
bytes memory sig = Memory.alloc(SIG_LENGTH);
bytes memory amount = Memory.alloc(AMOUNT_LENGTH);

// aggregate deposit data roots
bytes memory depositDataRoots;

for (uint256 i; i < _deposits; i++) {
// Copy pubkey, sig, and amount to the allocated memory slots
Memory.copy(_pubkeys, pubkey, i * PUBKEY_LENGTH, 0, PUBKEY_LENGTH);
Expand All @@ -84,8 +105,26 @@ library DepositLogistics {
uint256 amountInWei = _gweiBytesToWei(amount);
bytes32 root = _computeRoot(_creds, pubkey, sig, amount);

depositDataRoots = abi.encodePacked(depositDataRoots, root);

_depositContract.deposit{value: amountInWei}(pubkey, _creds, sig, root);
}

// reverts the deposit transaction if the current deposit root does not match the expected one.
// The expected deposit root is the one against which the guardian signature was produced, i.e.
// against which the deposit data was validated to make sure there were no deposits with these pubkeys,
// i.e. no deposit front-running.

// the guardians signs a concatenation of 3 things:
// 1. deposit prefix (a constant that reduces the signature validity space)
// 2. the deposit root against which the deposit data was validated
// 3. the aggregate of all deposit data roots

bytes32 currentDepositRoot = _depositContract.get_deposit_root();
bytes32 securityMessageHash = keccak256(abi.encodePacked(GUARDIAN_SIGNATURE_PREFIX, currentDepositRoot, depositDataRoots));
address signer = ECDSA.recover(securityMessageHash, _guardianSignature.r, _guardianSignature.vs);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it's worth to push this implementation a bit further over the abstraction path.

We can support ERC-1271 here and thus the other contract can be a guardian.
We can have an implementation of the "Lido Vaults DSM" as the guardian contract, so we can interchange them.
So, we can have some vaults protected by EOA guardian and some — by DSM committee.

WDYT?


if (signer != _guardian) revert InvalidGuardianSignature();
}

/**
Expand Down
9 changes: 6 additions & 3 deletions contracts/0.8.25/vaults/StakingVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -322,25 +322,28 @@ contract StakingVault is IStakingVault, IBeaconProxy, OwnableUpgradeable {
* @param _pubkeys Concatenated validator public keys
* @param _signatures Concatenated deposit data signatures
* @param _amounts Concatenated deposit amounts in gwei
* @param _guardianSignature Guardian signature (owner in this case)
* @dev Includes a check to ensure StakingVault is balanced before making deposits
*/
function depositToBeaconChain(
uint256 _numberOfDeposits,
bytes calldata _pubkeys,
bytes calldata _signatures,
bytes calldata _amounts
bytes calldata _amounts,
DepositLogistics.Signature memory _guardianSignature
) external {
if (_numberOfDeposits == 0) revert ZeroArgument("_numberOfDeposits");
if (!isBalanced()) revert Unbalanced();
if (msg.sender != _getStorage().operator) revert NotAuthorized("depositToBeaconChain", msg.sender);

DepositLogistics.processDeposits(
IDepositContract(address(DEPOSIT_CONTRACT)),
_numberOfDeposits,
bytes.concat(withdrawalCredentials()),
_pubkeys,
_signatures,
_amounts
_amounts,
_guardianSignature,
owner()
);

emit DepositedToBeaconChain(msg.sender, _numberOfDeposits);
Expand Down
5 changes: 4 additions & 1 deletion contracts/0.8.25/vaults/interfaces/IStakingVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// See contracts/COMPILERS.md
pragma solidity 0.8.25;

import { DepositLogistics } from "../../lib/DepositLogistics.sol";

/**
* @title IStakingVault
* @author Lido
Expand Down Expand Up @@ -36,7 +38,8 @@ interface IStakingVault {
uint256 _numberOfDeposits,
bytes calldata _pubkeys,
bytes calldata _signatures,
bytes calldata _sizes
bytes calldata _sizes,
DepositLogistics.Signature memory _guardianSignature
) external;
function requestValidatorExit(bytes calldata _pubkeys) external;
function lock(uint256 _locked) external;
Expand Down
Loading