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: Hyperlane AVS contracts #3651

Merged
merged 38 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c5ac704
forge install: eigenlayer-middleware
aroralanuk Apr 16, 2024
8873f20
install
aroralanuk Apr 22, 2024
2158670
getRestakeableStrategies
aroralanuk Apr 22, 2024
1ee6b10
comment
aroralanuk Apr 22, 2024
42ae9a6
enroll tc
aroralanuk Apr 23, 2024
325031e
add challenger
aroralanuk Apr 23, 2024
0488bc5
add enumerablemap
aroralanuk Apr 25, 2024
f737489
remove challengers
aroralanuk Apr 25, 2024
0eaffff
add unenroll tests
aroralanuk Apr 26, 2024
ef35202
fin testing
aroralanuk Apr 26, 2024
5c1c827
Merge branch 'main' into kunal/avs-contracts
aroralanuk Apr 26, 2024
a95a8c5
setSlasher
aroralanuk Apr 26, 2024
e348bdc
rm console.sol
aroralanuk Apr 26, 2024
5680d72
fix deregister bug
aroralanuk Apr 27, 2024
b8afaae
address yorke's comments
aroralanuk Apr 30, 2024
59c7019
Merge branch 'main' into kunal/avs-contracts
aroralanuk Apr 30, 2024
d7c2032
hardhat config filtering fail
aroralanuk Apr 30, 2024
01b1940
Revert "hardhat config filtering fail"
aroralanuk May 1, 2024
317d814
vendor interfaces fail
aroralanuk May 1, 2024
bf3e8df
vendor
aroralanuk May 4, 2024
421353e
Merge branch 'main' into kunal/avs-contracts
aroralanuk May 4, 2024
ff781c3
cleanup
aroralanuk May 4, 2024
05d7979
using steven's SMBase
aroralanuk May 6, 2024
df4a172
rm remapping upgrade
aroralanuk May 6, 2024
f045045
adding el core addresses
aroralanuk May 6, 2024
3abf566
Merge branch 'main' into kunal/avs-contracts
aroralanuk May 6, 2024
2ef337c
reading strategies from json
aroralanuk May 7, 2024
b50e0b2
add test for check man unenrollment
aroralanuk May 7, 2024
828f4e9
unenroll with address[]
aroralanuk May 7, 2024
7112431
function for single challenger enroll/unenroll
aroralanuk May 7, 2024
4cf5b02
separate vendored folder
aroralanuk May 7, 2024
7f3540b
add proxy deployment to forge
aroralanuk May 7, 2024
b159fdf
Merge branch 'main' into kunal/avs-contracts
aroralanuk May 7, 2024
23aa155
add global fuzz.runs config
aroralanuk May 7, 2024
e11ed99
update spelling
aroralanuk May 7, 2024
e62daa4
add incomp attribution to LL
aroralanuk May 7, 2024
b2e1643
deploy proxyAdmind
aroralanuk May 9, 2024
13f6da8
Merge branch 'main' into kunal/avs-contracts
aroralanuk May 9, 2024
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
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
typescript/sdk/src/cw-types/*.types.ts linguist-generated=true
rust/chains/hyperlane-ethereum/abis/*.abi.json linguist-generated=true
solidity/contracts/interfaces/avs/*.sol linguist-vendored=true
solidity/contracts/avs/ECDSA*.sol linguist-vendored=true
273 changes: 273 additions & 0 deletions solidity/contracts/avs/ECDSAServiceManagerBase.sol
aroralanuk marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;

import {ISignatureUtils} from "../interfaces/avs/vendored/ISignatureUtils.sol";
import {IAVSDirectory} from "../interfaces/avs/vendored/IAVSDirectory.sol";

import {IServiceManager} from "../interfaces/avs/vendored/IServiceManager.sol";
import {IServiceManagerUI} from "../interfaces/avs/vendored/IServiceManagerUI.sol";
import {IDelegationManager} from "../interfaces/avs/vendored/IDelegationManager.sol";
import {IStrategy} from "../interfaces/avs/vendored/IStrategy.sol";
import {IPaymentCoordinator} from "../interfaces/avs/vendored/IPaymentCoordinator.sol";
import {Quorum} from "../interfaces/avs/vendored/IECDSAStakeRegistryEventsAndErrors.sol";
import {ECDSAStakeRegistry} from "./ECDSAStakeRegistry.sol";

import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

/// @author Layr Labs, Inc.
abstract contract ECDSAServiceManagerBase is
IServiceManager,
OwnableUpgradeable
{
/// @notice Address of the stake registry contract, which manages registration and stake recording.
address public immutable stakeRegistry;

/// @notice Address of the AVS directory contract, which manages AVS-related data for registered operators.
address public immutable avsDirectory;

/// @notice Address of the delegation manager contract, which manages staker delegations to operators.
address internal immutable delegationManager;

// ============ Public Storage ============

/// @notice Address of the payment coordinator contract, which handles payment distributions. Will be set once live on Eigenlayer.
address internal paymentCoordinator;

// ============ Modifiers ============

/**
* @dev Ensures that the function is only callable by the `stakeRegistry` contract.
* This is used to restrict certain registration and deregistration functionality to the `stakeRegistry`
*/
modifier onlyStakeRegistry() {
require(
msg.sender == stakeRegistry,
"ECDSAServiceManagerBase.onlyStakeRegistry: caller is not the stakeRegistry"
);
_;
}

// ============ Events ============

/**
* @notice Emitted when an operator is registered to the AVS
* @param operator The address of the operator
*/
event OperatorRegisteredToAVS(address indexed operator);

/**
* @notice Emitted when an operator is deregistered from the AVS
* @param operator The address of the operator
*/
event OperatorDeregisteredFromAVS(address indexed operator);

// ============ Constructor ============

/**
* @dev Constructor for ECDSAServiceManagerBase, initializing immutable contract addresses and disabling initializers.
* @param _avsDirectory The address of the AVS directory contract, managing AVS-related data for registered operators.
* @param _stakeRegistry The address of the stake registry contract, managing registration and stake recording.
* @param _paymentCoordinator The address of the payment coordinator contract, handling payment distributions.
* @param _delegationManager The address of the delegation manager contract, managing staker delegations to operators.
*/
constructor(
address _avsDirectory,
address _stakeRegistry,
address _paymentCoordinator,
address _delegationManager
) {
avsDirectory = _avsDirectory;
stakeRegistry = _stakeRegistry;
paymentCoordinator = _paymentCoordinator;
delegationManager = _delegationManager;
}

/**
* @dev Initializes the base service manager by transferring ownership to the initial owner.
* @param initialOwner The address to which the ownership of the contract will be transferred.
*/
function __ServiceManagerBase_init(
address initialOwner
) internal virtual onlyInitializing {
_transferOwnership(initialOwner);
}

/// @inheritdoc IServiceManagerUI
function updateAVSMetadataURI(
string memory _metadataURI
) external virtual onlyOwner {
_updateAVSMetadataURI(_metadataURI);
}

/// @inheritdoc IServiceManager
function payForRange(
IPaymentCoordinator.RangePayment[] calldata rangePayments
) external virtual onlyOwner {
_payForRange(rangePayments);
}

/// @inheritdoc IServiceManagerUI
function registerOperatorToAVS(
address operator,
ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature
) external virtual onlyStakeRegistry {
_registerOperatorToAVS(operator, operatorSignature);
}

/// @inheritdoc IServiceManagerUI
function deregisterOperatorFromAVS(
address operator
) external virtual onlyStakeRegistry {
_deregisterOperatorFromAVS(operator);
}

/// @inheritdoc IServiceManagerUI
function getRestakeableStrategies()
external
view
virtual
returns (address[] memory)
{
return _getRestakeableStrategies();
}

/// @inheritdoc IServiceManagerUI
function getOperatorRestakedStrategies(
address _operator
) external view virtual returns (address[] memory) {
return _getOperatorRestakedStrategies(_operator);
}

/**
* @notice Sets the address of the payment coordinator contract.
* @dev This function is only callable by the contract owner.
* @param _paymentCoordinator The address of the payment coordinator contract.
*/
function setPaymentCoordinator(
address _paymentCoordinator

Check notice

Code scanning / Slither

Missing zero address validation Low

) external virtual onlyOwner {
paymentCoordinator = _paymentCoordinator;
}

/**
* @notice Forwards the call to update AVS metadata URI in the AVSDirectory contract.
* @dev This internal function is a proxy to the `updateAVSMetadataURI` function of the AVSDirectory contract.
* @param _metadataURI The new metadata URI to be set.
*/
function _updateAVSMetadataURI(
string memory _metadataURI
) internal virtual {
IAVSDirectory(avsDirectory).updateAVSMetadataURI(_metadataURI);
}

/**
* @notice Forwards the call to register an operator in the AVSDirectory contract.
* @dev This internal function is a proxy to the `registerOperatorToAVS` function of the AVSDirectory contract.
* @param operator The address of the operator to register.
* @param operatorSignature The signature, salt, and expiry details of the operator's registration.
*/
function _registerOperatorToAVS(
address operator,
ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature
) internal virtual {
IAVSDirectory(avsDirectory).registerOperatorToAVS(
operator,
operatorSignature
);
emit OperatorRegisteredToAVS(operator);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities Low


/**
* @notice Forwards the call to deregister an operator from the AVSDirectory contract.
* @dev This internal function is a proxy to the `deregisterOperatorFromAVS` function of the AVSDirectory contract.
* @param operator The address of the operator to deregister.
*/
function _deregisterOperatorFromAVS(address operator) internal virtual {
IAVSDirectory(avsDirectory).deregisterOperatorFromAVS(operator);
emit OperatorDeregisteredFromAVS(operator);
}

Check notice

Code scanning / Slither

Reentrancy vulnerabilities Low


/**
* @notice Processes a batch of range payments by transferring the specified amounts from the sender to this contract and then approving the PaymentCoordinator to use these amounts.
* @dev This function handles the transfer and approval of tokens necessary for range payments. It then delegates the actual payment logic to the PaymentCoordinator contract.
* @param rangePayments An array of `RangePayment` structs, each representing a payment for a specific range.
*/
function _payForRange(
IPaymentCoordinator.RangePayment[] calldata rangePayments
) internal virtual {
for (uint256 i = 0; i < rangePayments.length; ++i) {
rangePayments[i].token.transferFrom(
msg.sender,
address(this),
rangePayments[i].amount
);
rangePayments[i].token.approve(
paymentCoordinator,
rangePayments[i].amount
);
}

IPaymentCoordinator(paymentCoordinator).payForRange(rangePayments);
}

/**
* @notice Retrieves the addresses of all strategies that are part of the current quorum.
* @dev Fetches the quorum configuration from the ECDSAStakeRegistry and extracts the strategy addresses.
* @return strategies An array of addresses representing the strategies in the current quorum.
*/
function _getRestakeableStrategies()
internal
view
virtual
returns (address[] memory)
{
Quorum memory quorum = ECDSAStakeRegistry(stakeRegistry).quorum();
address[] memory strategies = new address[](quorum.strategies.length);
for (uint256 i = 0; i < quorum.strategies.length; i++) {
strategies[i] = address(quorum.strategies[i].strategy);
}
return strategies;
}

/**
* @notice Retrieves the addresses of strategies where the operator has restaked.
* @dev This function fetches the quorum details from the ECDSAStakeRegistry, retrieves the operator's shares for each strategy,
* and filters out strategies with non-zero shares indicating active restaking by the operator.
* @param _operator The address of the operator whose restaked strategies are to be retrieved.
* @return restakedStrategies An array of addresses of strategies where the operator has active restakes.
*/
function _getOperatorRestakedStrategies(
address _operator
) internal view virtual returns (address[] memory) {
Quorum memory quorum = ECDSAStakeRegistry(stakeRegistry).quorum();
uint256 count = quorum.strategies.length;
IStrategy[] memory strategies = new IStrategy[](count);
for (uint256 i; i < count; i++) {
strategies[i] = quorum.strategies[i].strategy;
}
uint256[] memory shares = IDelegationManager(delegationManager)
.getOperatorShares(_operator, strategies);

address[] memory activeStrategies = new address[](count);
uint256 activeCount;

Check warning

Code scanning / Slither

Uninitialized local variables Medium

for (uint256 i; i < count; i++) {
if (shares[i] > 0) {
activeCount++;
}
}

// Resize the array to fit only the active strategies
address[] memory restakedStrategies = new address[](activeCount);
for (uint256 j = 0; j < count; j++) {
if (shares[j] > 0) {
restakedStrategies[j] = activeStrategies[j];
}
}

return restakedStrategies;
}

// storage gap for upgradeability
// slither-disable-next-line shadowing-state
uint256[50] private __GAP;
}
Loading
Loading