The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
hyperlane-monorepo/solidity/script/avs/DeployAVS.s.sol

229 lines
8.5 KiB

// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
import "forge-std/Script.sol";
import {IStrategy} from "../../contracts/interfaces/avs/vendored/IStrategy.sol";
import {IAVSDirectory} from "../../contracts/interfaces/avs/vendored/IAVSDirectory.sol";
import {IPaymentCoordinator} from "../../contracts/interfaces/avs/vendored/IPaymentCoordinator.sol";
import {IDelegationManager} from "../../contracts/interfaces/avs/vendored/IDelegationManager.sol";
import {ProxyAdmin} from "../../contracts/upgrade/ProxyAdmin.sol";
import {TransparentUpgradeableProxy} from "../../contracts/upgrade/TransparentUpgradeableProxy.sol";
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {ECDSAStakeRegistry} from "../../contracts/avs/ECDSAStakeRegistry.sol";
import {Quorum, StrategyParams} from "../../contracts/interfaces/avs/vendored/IECDSAStakeRegistryEventsAndErrors.sol";
import {ECDSAServiceManagerBase} from "../../contracts/avs/ECDSAServiceManagerBase.sol";
import {HyperlaneServiceManager} from "../../contracts/avs/HyperlaneServiceManager.sol";
import {TestPaymentCoordinator} from "../../contracts/test/avs/TestPaymentCoordinator.sol";
contract DeployAVS is Script {
using stdJson for string;
struct StrategyInfo {
string name;
address strategy;
}
uint256 deployerPrivateKey;
ProxyAdmin public proxyAdmin;
IAVSDirectory public avsDirectory;
IPaymentCoordinator public paymentCoordinator;
IDelegationManager public delegationManager;
Quorum quorum;
uint256 thresholdWeight = 6667;
address KILN_OPERATOR_ADDRESS = 0x1f8C8b1d78d01bCc42ebdd34Fae60181bD697662;
function _loadEigenlayerAddresses(string memory targetEnv) internal {
string memory root = vm.projectRoot();
string memory path = string.concat(
root,
"/script/avs/eigenlayer_addresses.json"
);
string memory json = vm.readFile(path);
proxyAdmin = ProxyAdmin(
json.readAddress(
string(abi.encodePacked(".", targetEnv, ".proxyAdmin"))
)
);
avsDirectory = IAVSDirectory(
json.readAddress(
string(abi.encodePacked(".", targetEnv, ".avsDirectory"))
)
);
delegationManager = IDelegationManager(
json.readAddress(
string(abi.encodePacked(".", targetEnv, ".delegationManager"))
)
);
// paymentCoordinator = IPaymentCoordinator(json.readAddress(string(abi.encodePacked(".", targetEnv, ".paymentCoordinator"))));
paymentCoordinator = new TestPaymentCoordinator(); // temporary until Eigenlayer deploys the real one
StrategyInfo[] memory strategies = abi.decode(
vm.parseJson(
json,
string(abi.encodePacked(".", targetEnv, ".strategies"))
),
(StrategyInfo[])
);
StrategyParams memory strategyParam;
uint96 totalMultipliers = 10_000;
uint96 multiplier;
uint96 strategyCount = uint96(strategies.length);
for (uint96 i = 0; i < strategyCount; i++) {
// the multipliers need to add up to 10,000, so we divide the total by the number of strategies for the first n-1 strategies
// and then the last strategy gets the remainder
if (i < strategyCount - 1) {
multiplier = totalMultipliers / uint96(strategyCount);
} else {
multiplier =
totalMultipliers -
multiplier *
uint96(strategyCount - 1);
}
strategyParam = StrategyParams({
strategy: IStrategy(strategies[i].strategy),
multiplier: multiplier
});
quorum.strategies.push(strategyParam);
}
}
function run(string memory network, string memory metadataUri) external {
deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
address deployerAddress = vm.addr(deployerPrivateKey);
_loadEigenlayerAddresses(network);
vm.startBroadcast(deployerPrivateKey);
ECDSAStakeRegistry stakeRegistryImpl = new ECDSAStakeRegistry(
delegationManager
);
TransparentUpgradeableProxy stakeRegistryProxy = new TransparentUpgradeableProxy(
address(stakeRegistryImpl),
address(proxyAdmin),
""
);
HyperlaneServiceManager strategyManagerImpl = new HyperlaneServiceManager(
address(avsDirectory),
address(stakeRegistryProxy),
address(paymentCoordinator),
address(delegationManager)
);
TransparentUpgradeableProxy hsmProxy = new TransparentUpgradeableProxy(
address(strategyManagerImpl),
address(proxyAdmin),
abi.encodeWithSelector(
HyperlaneServiceManager.initialize.selector,
address(deployerAddress)
)
);
// Initialize the ECDSAStakeRegistry once we have the HyperlaneServiceManager proxy
(bool success, ) = address(stakeRegistryProxy).call(
abi.encodeWithSelector(
ECDSAStakeRegistry.initialize.selector,
address(hsmProxy),
thresholdWeight,
quorum
)
);
HyperlaneServiceManager hsm = HyperlaneServiceManager(
address(hsmProxy)
);
require(success, "Failed to initialize ECDSAStakeRegistry");
require(
ECDSAStakeRegistry(address(stakeRegistryProxy)).owner() ==
address(deployerAddress),
"Owner of ECDSAStakeRegistry is not the deployer"
);
require(
HyperlaneServiceManager(address(hsmProxy)).owner() ==
address(deployerAddress),
"Owner of HyperlaneServiceManager is not the deployer"
);
hsm.updateAVSMetadataURI(metadataUri);
console.log(
"ECDSAStakeRegistry Implementation: ",
address(stakeRegistryImpl)
);
console.log(
"HyperlaneServiceManager Implementation: ",
address(strategyManagerImpl)
);
console.log("StakeRegistry Proxy: ", address(stakeRegistryProxy));
console.log("HyperlaneServiceManager Proxy: ", address(hsmProxy));
vm.stopBroadcast();
}
// upgrade for https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4090
function upgradeHsm4090(
string memory network,
address hsmProxy,
address stakeRegistryProxy
) external {
deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
_loadEigenlayerAddresses(network);
vm.startBroadcast(deployerPrivateKey);
// check original behavior
HyperlaneServiceManager hsm = HyperlaneServiceManager(hsmProxy);
address[] memory strategies = hsm.getOperatorRestakedStrategies(
KILN_OPERATOR_ADDRESS
);
require(strategies.length > 0, "No strategies found for operator"); // actual length is 13
// for (uint256 i = 0; i < strategies.length; i++) {
// vm.expectRevert(); // all strategies are expected to be 0x0..0
// require(strategies[i] != address(0), "Strategy address is 0");
// }
HyperlaneServiceManager strategyManagerImpl = new HyperlaneServiceManager(
address(avsDirectory),
stakeRegistryProxy,
address(paymentCoordinator),
address(delegationManager)
);
console.log("Deployed new impl at", address(strategyManagerImpl));
bytes memory encodedUpgradeCalldata = abi.encodeCall(
ProxyAdmin.upgrade,
(
ITransparentUpgradeableProxy(payable(hsmProxy)),
address(strategyManagerImpl)
)
);
console.log("Encoded upgrade call: ");
console.logBytes(encodedUpgradeCalldata);
vm.stopBroadcast();
// only meant for simulating the call on mainnet as the actual caller needs to the gnosis safe
address(proxyAdmin).call(encodedUpgradeCalldata);
// check upgraded behavior
strategies = hsm.getOperatorRestakedStrategies(KILN_OPERATOR_ADDRESS);
require(strategies.length > 0, "No strategies found for operator"); // actual length is 13
for (uint256 i = 0; i < strategies.length; i++) {
require(strategies[i] != address(0), "Strategy address is 0");
}
}
}