Skip to content

Commit

Permalink
chore: adding strategy deployments back to EigenLayerSetup
Browse files Browse the repository at this point in the history
  • Loading branch information
nican0r committed Jun 25, 2024
1 parent d51cf72 commit befdce7
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 834 deletions.
274 changes: 108 additions & 166 deletions src/test/recon/EigenLayerSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ import {StrategyManager} from "../../../src/contracts/core/StrategyManager.sol";
import {EigenPod} from "../../../src/contracts/pods/EigenPod.sol";
import {EigenPodManager} from "../../../src/contracts/pods/EigenPodManager.sol";
import {DelayedWithdrawalRouter} from "../../../src/contracts/pods/DelayedWithdrawalRouter.sol";
import {BeaconChainOracleMock} from "../../../src/test/mocks/BeaconChainOracleMock.sol";
import {PauserRegistry} from "../../../src/contracts/permissions/PauserRegistry.sol";
import {StrategyManager} from "../../../src/contracts/core/StrategyManager.sol";
import {StrategyBase} from "../../../src/contracts/strategies/StrategyBase.sol";
import {EmptyContract} from "../../../src/test/mocks/EmptyContract.sol";
import {StrategyBaseTVLLimits} from "../../../src/contracts/strategies/StrategyBaseTVLLimits.sol";
import {IStrategy} from "../../../src/contracts/interfaces/IStrategy.sol";
import {IBeaconChainOracle} from "../../../src/contracts/interfaces/IBeaconChainOracle.sol";

import {MockERC20} from "../mocks/MockERC20.sol";
import "forge-std/console2.sol";

// this contract deploys the EigenLayer system for use by an integrating system
Expand Down Expand Up @@ -52,33 +51,15 @@ contract EigenLayerSetup {
EigenPod internal eigenPodImplementation;
StrategyBase internal baseStrategyImplementation;
IStrategy[] internal strategies;
MockERC20 internal stETH;
MockERC20 internal wbETH;
EmptyContract internal emptyContract;
ETHPOSDepositMock internal ethPOSDepositMock; // BeaconChain deposit contract
StrategyBaseTVLLimits[] internal deployedStrategyArray; // strategies deployed locally
StrategyBase[] internal deployedForkStrategyArray; // strategies deployed on mainnet
uint256[] internal withdrawalDelayBlocks;
address[] internal tokenAddresses;

// addresses for fork testing
address internal eigenLayerPauserRegAddress;
address internal delegationAddress;
address internal strategyManagerAddress;
address internal slasherAddress;
address internal eigenPodManagerAddress;
address internal delayedWithdrawalRouterAddress;
address internal operationsMultisig;
address internal executorMultisig;
address internal beaconChainOracleAddress;
address internal eigenPodBeaconAddress;
address internal cbETHStrategyAddress;
address internal stETHStrategyAddress;

// strategies deployed
StrategyBaseTVLLimits[] internal deployedStrategyArray;
// strategies deployed on mainnet
StrategyBase[] internal deployedForkStrategyArray;

EmptyContract internal emptyContract;

// BeaconChain deposit contract & beacon chain oracle
ETHPOSDepositMock internal ethPOSDepositMock;
address internal beaconChainOracle;
address internal beaconChainOracle; // beacon chain oracle

// NOTE: this replaces all multisig accounts in the deployment script
address admin = address(this);
Expand All @@ -99,31 +80,70 @@ contract EigenLayerSetup {
/**
@notice Deploys the entire EigenLayer system locally
@dev Strategies are deployed for the tokenAddresses and tokenSymbols passed in
@param _tokenAddresses The LST addresses to deploy strategies for
NOTE: This copies the logic of the M1_Deploy script to deploy the entire system
*/
function deployEigenLayerLocal(address[] memory _tokenAddresses) internal {
// save tokenAddresses to state
tokenAddresses = _tokenAddresses;

// tokens to deploy strategies for
StrategyConfig[] memory strategyConfigs = new StrategyConfig[](_tokenAddresses.length);

function deployEigenLayerLocal() internal {
// deploy proxy admin for ability to upgrade proxy contracts
vm.prank(admin);
eigenLayerProxyAdmin = new ProxyAdmin();

//deploy pauser registry
{
address[] memory pausers = new address[](1);
pausers[0] = admin;
eigenLayerPauserReg = new PauserRegistry(pausers, admin);
}
_deployPauserRegistry();

/**
First the upgradeable proxy contracts that will point to implementation contracts get deployed.
Since implementation contracts aren't yet deployed, they pass in an empty contract as a placeholder
*/
_deployUpgradeableContracts();

ethPOSDepositMock = new ETHPOSDepositMock();
eigenPodImplementation = new EigenPod(
ethPOSDepositMock,
delayedWithdrawalRouter,
eigenPodManager,
uint64(MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR),
GENESIS_TIME
);
eigenPodBeacon = new UpgradeableBeacon(address(eigenPodImplementation));

// Second, deploy the *implementation* contracts, using the *proxy contracts* as inputs
_deployImplementationContracts();
// Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them.
_upgradeProxies();

_deployTokens();
_deployStrategies();

// CHECK CORRECTNESS OF DEPLOYMENT
_verifyContractsPointAtOneAnother(
delegationImplementation,
strategyManagerImplementation,
slasherImplementation,
eigenPodManagerImplementation,
delayedWithdrawalRouterImplementation
);
_verifyContractsPointAtOneAnother(
delegation,
strategyManager,
slasher,
eigenPodManager,
delayedWithdrawalRouter
);
_verifyImplementationsSetCorrectly();
_verifyInitialOwners();
_checkPauserInitializations();
_verifyInitializationParams();
}

/**
System Deployments
*/
function _deployPauserRegistry() internal {
address[] memory pausers = new address[](1);
pausers[0] = admin;
eigenLayerPauserReg = new PauserRegistry(pausers, admin);
}

function _deployUpgradeableContracts() internal {
emptyContract = new EmptyContract();
delegation = DelegationManager(
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
Expand All @@ -140,23 +160,9 @@ contract EigenLayerSetup {
delayedWithdrawalRouter = DelayedWithdrawalRouter(
address(new TransparentUpgradeableProxy(address(emptyContract), address(eigenLayerProxyAdmin), ""))
);
}

// deploy the ethPOS
ethPOSDepositMock = new ETHPOSDepositMock();

// deploy EigenPod
eigenPodImplementation = new EigenPod(
ethPOSDepositMock,
delayedWithdrawalRouter,
eigenPodManager,
uint64(MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR),
GENESIS_TIME
);

// this is used in EigenPodManager to set the implementation that supplies source bytecode every time a new pod is deployed
eigenPodBeacon = new UpgradeableBeacon(address(eigenPodImplementation));

// Second, deploy the *implementation* contracts, using the *proxy contracts* as inputs
function _deployImplementationContracts() internal {
delegationImplementation = new DelegationManager(strategyManager, slasher, eigenPodManager);
strategyManagerImplementation = new StrategyManager(delegation, eigenPodManager, slasher);
slasherImplementation = new Slasher(strategyManager, delegation);
Expand All @@ -167,10 +173,10 @@ contract EigenLayerSetup {
slasher,
delegation
);

delayedWithdrawalRouterImplementation = new DelayedWithdrawalRouter(eigenPodManager);
}

// Third, upgrade the proxy contracts to use the correct implementation contracts and initialize them.
function _upgradeProxies() internal {
eigenLayerProxyAdmin.upgradeAndCall(
ITransparentUpgradeableProxy(payable(address(delegation))),
address(delegationImplementation),
Expand All @@ -180,8 +186,6 @@ contract EigenLayerSetup {
eigenLayerPauserReg,
DELEGATION_INIT_PAUSED_STATUS,
DELEGATION_INIT_WITHDRAWAL_DELAY_BLOCKS,
// NOTE: passing in empty arrays for these two for now while figuring out how to deploy strategies
// TODO: change these once strategy deployments are handled
strategies,
withdrawalDelayBlocks
)
Expand Down Expand Up @@ -226,10 +230,21 @@ contract EigenLayerSetup {
DELAYED_WITHDRAWAL_ROUTER_INIT_WITHDRAWAL_DELAY_BLOCKS
)
);
}

function _deployTokens() internal {
stETH = new MockERC20("lido staked ETH", "stETH", 18);
wbETH = new MockERC20("binance staked ETH", "wbETH", 18);

tokenAddresses = new address[](2);
tokenAddresses[0] = address(stETH);
tokenAddresses[1] = address(wbETH);
}

function _deployStrategies() internal {
baseStrategyImplementation = new StrategyBaseTVLLimits(strategyManager);
// creates upgradeable proxies of strategies that each point to the implementation and initialize them
for (uint256 i = 0; i < _tokenAddresses.length; ++i) {
for (uint256 i = 0; i < tokenAddresses.length; ++i) {
deployedStrategyArray.push(
StrategyBaseTVLLimits(
address(
Expand All @@ -240,7 +255,7 @@ contract EigenLayerSetup {
StrategyBaseTVLLimits.initialize.selector,
type(uint256).max,
type(uint256).max,
IERC20(_tokenAddresses[i]),
IERC20(tokenAddresses[i]),
eigenLayerPauserReg
)
)
Expand All @@ -251,91 +266,17 @@ contract EigenLayerSetup {

// set the strategy whitelist in strategyManager
bool[] memory thirdPartyTransfers = new bool[](deployedStrategyArray.length); // default to allowing third party transfers
IStrategy[] memory simpleStrategyArray = new IStrategy[](deployedStrategyArray.length);

// create an array of strategies using their interfaces to be able to pass into strategyManager whitelisting
// create an array of strategies with IStrategy interface to be able to pass into strategyManager whitelisting
for (uint256 i = 0; i < deployedStrategyArray.length; ++i) {
simpleStrategyArray[i] = IStrategy(address(deployedStrategyArray[i]));
}
strategyManager.addStrategiesToDepositWhitelist(simpleStrategyArray, thirdPartyTransfers);

// CHECK CORRECTNESS OF DEPLOYMENT
_verifyContractsPointAtOneAnother(
delegationImplementation,
strategyManagerImplementation,
slasherImplementation,
eigenPodManagerImplementation,
delayedWithdrawalRouterImplementation
);
_verifyContractsPointAtOneAnother(
delegation,
strategyManager,
slasher,
eigenPodManager,
delayedWithdrawalRouter
);
_verifyImplementationsSetCorrectly();
_verifyInitialOwners();
_checkPauserInitializations();
_verifyInitializationParams();
}

function deployEigenLayerForked(address[] memory _strategies) internal {
_setAddresses();
// what actually needs to be deployed here if EigenLayer is already deployed on mainnet?
// TODO: need to use the admin address to grant permissions to admin account here or mock the deployed admin

// TODO: need to read deployed contract state to figure out what account is proxy admin
// eigenLayerProxyAdmin = ProxyAdmin(eigenLayerProxyAdminAddress);

eigenLayerPauserReg = PauserRegistry(eigenLayerPauserRegAddress);

delegation = DelegationManager(delegationAddress);
strategyManager = StrategyManager(strategyManagerAddress);
slasher = Slasher(slasherAddress);
eigenPodManager = EigenPodManager(eigenPodManagerAddress);
delayedWithdrawalRouter = DelayedWithdrawalRouter(delayedWithdrawalRouterAddress);

// don't need to mock the ETHPOS deposit contract because deployed EigenPod points to it
eigenPodBeacon = UpgradeableBeacon(eigenPodBeaconAddress);

deployedForkStrategyArray = new StrategyBase[](_strategies.length);
console2.log("strategies length: ", _strategies.length);
// get the deployed strategies used in Renzo to use here
deployedForkStrategyArray.push(StrategyBase(_strategies[0]));
deployedForkStrategyArray.push(StrategyBase(_strategies[1]));

// set the strategy whitelist in strategyManager
bool[] memory thirdPartyTransfers = new bool[](_strategies.length); // default to allowing third party transfers
IStrategy[] memory simpleStrategyArray = new IStrategy[](_strategies.length);

// create an array of strategies using their interfaces to be able to pass into strategyManager whitelisting
// NOTE: may cause issue that leads to revert when testing
for (uint256 i = 0; i < _strategies.length; ++i) {
simpleStrategyArray[i] = IStrategy(address(deployedForkStrategyArray[i]));
strategies.push() = IStrategy(address(deployedStrategyArray[i]));
}
strategyManager.addStrategiesToDepositWhitelist(simpleStrategyArray, thirdPartyTransfers);
}

// @audit this function sets contract addresses with those deployed on mainnet
function _setAddresses() internal {
// eigenLayerProxyAdminAddress = stdJson.readAddress(config, ".addresses.eigenLayerProxyAdmin");
eigenLayerPauserRegAddress = address(0x0c431C66F4dE941d089625E5B423D00707977060);
// NOTE: the following addresses are the proxies, not implementation
delegationAddress = address(0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A);
strategyManagerAddress = address(0x858646372CC42E1A627fcE94aa7A7033e7CF075A);
slasherAddress = address(0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd);
eigenPodManagerAddress = address(0x91E677b07F7AF907ec9a428aafA9fc14a0d3A338);
delayedWithdrawalRouterAddress = address(0x7Fe7E9CC0F274d2435AD5d56D5fa73E47F6A23D8);
beaconChainOracleAddress = address(0x343907185b71aDF0eBa9567538314396aa985442);
eigenPodBeaconAddress = address(0x5a2a4F2F3C18f09179B6703e63D9eDD165909073);
cbETHStrategyAddress = address(0x54945180dB7943c0ed0FEE7EdaB2Bd24620256bc);
stETHStrategyAddress = address(0x93c4b944D05dfe6df7645A86cd2206016c51564D);

operationsMultisig = address(0xBE1685C81aA44FF9FB319dD389addd9374383e90);
executorMultisig = address(0x369e6F597e22EaB55fFb173C6d9cD234BD699111);
strategyManager.addStrategiesToDepositWhitelist(strategies, thirdPartyTransfers);
}

/**
Deployment Verifications
*/
function _verifyContractsPointAtOneAnother(
DelegationManager delegationContract,
StrategyManager strategyManagerContract,
Expand Down Expand Up @@ -416,14 +357,15 @@ contract EigenLayerSetup {
"delayedWithdrawalRouter: implementation set incorrectly"
);

for (uint256 i = 0; i < deployedStrategyArray.length; ++i) {
require(
eigenLayerProxyAdmin.getProxyImplementation(
ITransparentUpgradeableProxy(payable(address(deployedStrategyArray[i])))
) == address(baseStrategyImplementation),
"strategy: implementation set incorrectly"
);
}
// @audit deployed strategy checks are no longer needed
// for (uint256 i = 0; i < deployedStrategyArray.length; ++i) {
// require(
// eigenLayerProxyAdmin.getProxyImplementation(
// ITransparentUpgradeableProxy(payable(address(deployedStrategyArray[i])))
// ) == address(baseStrategyImplementation),
// "strategy: implementation set incorrectly"
// );
// }

require(
eigenPodBeacon.implementation() == address(eigenPodImplementation),
Expand Down Expand Up @@ -465,16 +407,16 @@ contract EigenLayerSetup {
require(eigenLayerPauserReg.isPauser(admin), "pauserRegistry: pauserMultisig is not pauser");
require(eigenLayerPauserReg.unpauser() == admin, "pauserRegistry: unpauser not set correctly");

for (uint256 i = 0; i < deployedStrategyArray.length; ++i) {
require(
deployedStrategyArray[i].pauserRegistry() == eigenLayerPauserReg,
"StrategyBaseTVLLimits: pauser registry not set correctly"
);
require(
deployedStrategyArray[i].paused() == 0,
"StrategyBaseTVLLimits: init paused status set incorrectly"
);
}
// for (uint256 i = 0; i < deployedStrategyArray.length; ++i) {
// require(
// deployedStrategyArray[i].pauserRegistry() == eigenLayerPauserReg,
// "StrategyBaseTVLLimits: pauser registry not set correctly"
// );
// require(
// deployedStrategyArray[i].paused() == 0,
// "StrategyBaseTVLLimits: init paused status set incorrectly"
// );
// }

// // pause *nothing*
// uint256 STRATEGY_MANAGER_INIT_PAUSED_STATUS = 0;
Expand All @@ -493,7 +435,7 @@ contract EigenLayerSetup {
require(delayedWithdrawalRouter.paused() == 0, "delayedWithdrawalRouter: init paused status set incorrectly");
}

function _verifyInitializationParams() internal {
function _verifyInitializationParams() internal view {
// // one week in blocks -- 50400
// uint32 STRATEGY_MANAGER_INIT_WITHDRAWAL_DELAY_BLOCKS = 7 days / 12 seconds;
// uint32 DELAYED_WITHDRAWAL_ROUTER_INIT_WITHDRAWAL_DELAY_BLOCKS = 7 days / 12 seconds;
Expand All @@ -518,10 +460,10 @@ contract EigenLayerSetup {
"delayedWithdrawalRouter: eigenPodManager set incorrectly"
);

require(
baseStrategyImplementation.strategyManager() == strategyManager,
"baseStrategyImplementation: strategyManager set incorrectly"
);
// require(
// baseStrategyImplementation.strategyManager() == strategyManager,
// "baseStrategyImplementation: strategyManager set incorrectly"
// );

require(
eigenPodImplementation.ethPOS() == ethPOSDepositMock,
Expand Down
Loading

0 comments on commit befdce7

Please sign in to comment.