-
Notifications
You must be signed in to change notification settings - Fork 238
feat: Verifiable Deployment Calldata script #1415
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
Changes from 2 commits
a08a43b
b1fc353
9c4d86b
7e7fa97
e1e1449
acf9096
fc54040
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,8 @@ import {VersionedBlobParams} from "src/interfaces/IEigenDAStructs.sol"; | |
import {MockStakeRegistry} from "./mocks/MockStakeRegistry.sol"; | ||
import {MockRegistryCoordinator} from "./mocks/MockRegistryCoordinator.sol"; | ||
|
||
import {BeforeInitialization} from "./test/BeforeInitialization.t.sol"; | ||
|
||
import { | ||
DeploymentInitializer, | ||
ImmutableInitParams, | ||
|
@@ -44,15 +46,16 @@ import { | |
CalldataInitParams, | ||
CalldataRegistryCoordinatorParams, | ||
CalldataThresholdRegistryParams, | ||
CalldataServiceManagerParams | ||
CalldataServiceManagerParams, | ||
InitParamsLib | ||
} from "./DeploymentInitializer.sol"; | ||
|
||
import "forge-std/Script.sol"; | ||
import "forge-std/StdJson.sol"; | ||
import {console2} from "forge-std/console2.sol"; | ||
|
||
contract DeployVerifiable is Script { | ||
// The intended owner of all the contracts after the full deployment process is completed. | ||
address initialOwner; | ||
using InitParamsLib for string; | ||
|
||
// All proxies and implementations to upgrade them to, namespaced in structs. | ||
ProxyAdmin proxyAdmin; | ||
|
@@ -62,15 +65,6 @@ contract DeployVerifiable is Script { | |
// Contracts deployed without a proxy | ||
IPauserRegistry pauserRegistry; | ||
|
||
// Configuration parameters for construction of implementations | ||
address rewardsCoordinator; | ||
address avsDirectory; | ||
address delegationManager; | ||
address churnApprover; | ||
address ejector; | ||
|
||
uint256 initialPausedStatus; | ||
|
||
// Inert implementation contracts used as initial implementations before the proxies are initialized | ||
address emptyContract; | ||
address mockStakeRegistry; | ||
|
@@ -80,32 +74,17 @@ contract DeployVerifiable is Script { | |
DeploymentInitializer deploymentInitializer; | ||
|
||
// Script config | ||
string configData; | ||
|
||
/// @dev override this if you don't want to use the environment to get the config path | ||
function _configPath() internal view virtual returns (string memory) { | ||
return vm.envString("DEPLOY_CONFIG_PATH"); | ||
} | ||
string cfg; | ||
|
||
function run() public { | ||
// Read JSON config | ||
configData = vm.readFile(_configPath()); | ||
initialOwner = stdJson.readAddress(configData, ".initialOwner"); | ||
rewardsCoordinator = stdJson.readAddress(configData, ".initParams.shared.rewardsCoordinator"); | ||
avsDirectory = stdJson.readAddress(configData, ".initParams.shared.avsDirectory"); | ||
delegationManager = stdJson.readAddress(configData, ".initParams.shared.delegationManager"); | ||
initialPausedStatus = stdJson.readUint(configData, ".initParams.shared.initialPausedStatus"); | ||
_initConfig(); | ||
|
||
vm.startBroadcast(); | ||
proxyAdmin = new ProxyAdmin(); | ||
emptyContract = address(new EmptyContract()); | ||
mockStakeRegistry = address(new MockStakeRegistry(IDelegationManager(delegationManager))); | ||
pauserRegistry = IPauserRegistry( | ||
new PauserRegistry( | ||
stdJson.readAddressArray(configData, ".initParams.core.pauserRegistry.pausers"), | ||
stdJson.readAddress(configData, ".initParams.core.pauserRegistry.unpauser") | ||
) | ||
); | ||
mockStakeRegistry = address(new MockStakeRegistry(IDelegationManager(cfg.delegationManager()))); | ||
pauserRegistry = IPauserRegistry(new PauserRegistry(cfg.pausers(), cfg.unpauser())); | ||
|
||
_deployInertProxies(); | ||
_deployImplementations(); | ||
|
@@ -116,24 +95,49 @@ contract DeployVerifiable is Script { | |
// Transfer ownership of proxy admin to deployment initializer | ||
proxyAdmin.transferOwnership(address(deploymentInitializer)); | ||
|
||
_logs(); | ||
|
||
vm.stopBroadcast(); | ||
|
||
_doTests(configData); | ||
_doTests(); | ||
} | ||
|
||
/// @dev override this if you don't want to use the environment to get the config path | ||
function _initConfig() internal virtual { | ||
cfg = vm.readFile(vm.envString("DEPLOY_CONFIG_PATH")); | ||
} | ||
|
||
function _doTests(string memory cfg) internal { | ||
vm.startPrank(initialOwner); | ||
CalldataInitParams memory params = CalldataInitParamsLib.getCalldataInitParams(cfg); | ||
function _logs() internal virtual { | ||
console2.log("Deployment addresses:"); | ||
console2.log("Deployment Initializer: ", address(deploymentInitializer)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit - inconsistent formatting with other log stmts There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
console2.log("Empty Contract Implementation", emptyContract); | ||
console2.log("Mock Stake Registry Implementation", mockStakeRegistry); | ||
console2.log("Mock Registry Coordinator Implementation", mockRegistryCoordinator); | ||
|
||
console2.log( | ||
"\n\nAll other relevant deployment addresses should be queried from the DeploymentInitializer contract." | ||
); | ||
} | ||
|
||
function _doTests() internal { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this not a redundant simulation with just running the script with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How so? I don't think I understand this question. Do you mean that this whole fn is redundant? Basically this function is put into the script to run the same tests that the verifier would run to verify the deployment. That way, the deployer has some assurance that the verifier can run the BeforeVerifiableDeploymentInitialization test on the latest block on the deployed chain and have it pass. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah I see that makes sense - any chance we could capture this role differentiation in a smol comment? At first glance the behavior is a bit hard to decipher There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
BeforeInitialization beforeTest = new BeforeInitialization(); | ||
beforeTest.doBeforeInitializationTests( | ||
cfg, deploymentInitializer, emptyContract, mockStakeRegistry, mockRegistryCoordinator | ||
); | ||
|
||
vm.startPrank(cfg.initialOwner()); | ||
CalldataInitParams memory params = InitParamsLib.calldataInitParams(cfg); | ||
deploymentInitializer.initializeDeployment(params); | ||
|
||
// TODO: Add more tests | ||
|
||
vm.stopPrank(); | ||
} | ||
|
||
function _deployInertProxies() internal virtual { | ||
proxyAdmin = new ProxyAdmin(); | ||
emptyContract = address(new EmptyContract()); | ||
mockStakeRegistry = address(new MockStakeRegistry(IDelegationManager(delegationManager))); | ||
mockStakeRegistry = address(new MockStakeRegistry(IDelegationManager(cfg.delegationManager()))); | ||
|
||
// Deploy empty contracts to get addresses | ||
proxies.indexRegistry = address(new TransparentUpgradeableProxy(emptyContract, address(proxyAdmin), "")); | ||
|
@@ -158,7 +162,9 @@ contract DeployVerifiable is Script { | |
function _deployImplementations() internal virtual { | ||
implementations.indexRegistry = address(new IndexRegistry(IRegistryCoordinator(proxies.registryCoordinator))); | ||
implementations.stakeRegistry = address( | ||
new StakeRegistry(IRegistryCoordinator(proxies.registryCoordinator), IDelegationManager(delegationManager)) | ||
new StakeRegistry( | ||
IRegistryCoordinator(proxies.registryCoordinator), IDelegationManager(cfg.delegationManager()) | ||
) | ||
); | ||
implementations.socketRegistry = address(new SocketRegistry(IRegistryCoordinator(proxies.registryCoordinator))); | ||
implementations.blsApkRegistry = address(new BLSApkRegistry(IRegistryCoordinator(proxies.registryCoordinator))); | ||
|
@@ -177,8 +183,8 @@ contract DeployVerifiable is Script { | |
implementations.disperserRegistry = address(new EigenDADisperserRegistry()); | ||
implementations.serviceManager = address( | ||
new EigenDAServiceManager( | ||
IAVSDirectory(avsDirectory), | ||
IRewardsCoordinator(rewardsCoordinator), | ||
IAVSDirectory(cfg.avsDirectory()), | ||
IRewardsCoordinator(cfg.rewardsCoordinator()), | ||
IRegistryCoordinator(proxies.registryCoordinator), | ||
IStakeRegistry(proxies.stakeRegistry), | ||
IEigenDAThresholdRegistry(proxies.thresholdRegistry), | ||
|
@@ -190,110 +196,16 @@ contract DeployVerifiable is Script { | |
} | ||
|
||
function _immutableInitParams() internal view returns (ImmutableInitParams memory) { | ||
ImmutableRegistryCoordinatorParams memory registryCoordinatorParams = ImmutableRegistryCoordinatorParams({ | ||
churnApprover: stdJson.readAddress(configData, ".initParams.middleware.registryCoordinator.churnApprover"), | ||
ejector: stdJson.readAddress(configData, ".initParams.middleware.registryCoordinator.ejector") | ||
}); | ||
ImmutablePaymentVaultParams memory paymentVaultParams = ImmutablePaymentVaultParams({ | ||
minNumSymbols: uint64(stdJson.readUint(configData, ".initParams.eigenDA.paymentVault.minNumSymbols")), | ||
pricePerSymbol: uint64(stdJson.readUint(configData, ".initParams.eigenDA.paymentVault.pricePerSymbol")), | ||
priceUpdateCooldown: uint64( | ||
stdJson.readUint(configData, ".initParams.eigenDA.paymentVault.priceUpdateCooldown") | ||
), | ||
globalSymbolsPerPeriod: uint64( | ||
stdJson.readUint(configData, ".initParams.eigenDA.paymentVault.globalSymbolsPerPeriod") | ||
), | ||
reservationPeriodInterval: uint64( | ||
stdJson.readUint(configData, ".initParams.eigenDA.paymentVault.reservationPeriodInterval") | ||
), | ||
globalRatePeriodInterval: uint64( | ||
stdJson.readUint(configData, ".initParams.eigenDA.paymentVault.globalRatePeriodInterval") | ||
) | ||
}); | ||
ImmutableServiceManagerParams memory serviceManagerParams = ImmutableServiceManagerParams({ | ||
rewardsInitiator: stdJson.readAddress(configData, ".initParams.eigenDA.serviceManager.rewardsInitiator") | ||
}); | ||
|
||
return ImmutableInitParams({ | ||
proxyAdmin: proxyAdmin, | ||
initialOwner: initialOwner, | ||
initialOwner: cfg.initialOwner(), | ||
pauserRegistry: pauserRegistry, | ||
initialPausedStatus: initialPausedStatus, | ||
initialPausedStatus: cfg.initialPausedStatus(), | ||
proxies: proxies, | ||
implementations: implementations, | ||
registryCoordinatorParams: registryCoordinatorParams, | ||
paymentVaultParams: paymentVaultParams, | ||
serviceManagerParams: serviceManagerParams | ||
}); | ||
} | ||
} | ||
|
||
library CalldataInitParamsLib { | ||
function operatorSetParams(string memory configData) | ||
internal | ||
pure | ||
returns (IRegistryCoordinator.OperatorSetParam[] memory) | ||
{ | ||
bytes memory operatorConfigsRaw = | ||
stdJson.parseRaw(configData, ".initParams.middleware.registryCoordinator.operatorSetParams"); | ||
return abi.decode(operatorConfigsRaw, (IRegistryCoordinator.OperatorSetParam[])); | ||
} | ||
|
||
function minimumStakes(string memory configData) internal pure returns (uint96[] memory) { | ||
bytes memory stakesConfigsRaw = | ||
stdJson.parseRaw(configData, ".initParams.middleware.registryCoordinator.minimumStakes"); | ||
return abi.decode(stakesConfigsRaw, (uint96[])); | ||
} | ||
|
||
function strategyParams(string memory configData) | ||
internal | ||
pure | ||
returns (IStakeRegistry.StrategyParams[][] memory) | ||
{ | ||
bytes memory strategyConfigsRaw = | ||
stdJson.parseRaw(configData, ".initParams.middleware.registryCoordinator.strategyParams"); | ||
return abi.decode(strategyConfigsRaw, (IStakeRegistry.StrategyParams[][])); | ||
} | ||
|
||
function quorumAdversaryThresholdPercentages(string memory configData) internal pure returns (bytes memory) { | ||
return | ||
stdJson.readBytes(configData, ".initParams.eigenDA.thresholdRegistry.quorumAdversaryThresholdPercentages"); | ||
} | ||
|
||
function quorumConfirmationThresholdPercentages(string memory configData) internal pure returns (bytes memory) { | ||
return stdJson.readBytes( | ||
configData, ".initParams.eigenDA.thresholdRegistry.quorumConfirmationThresholdPercentages" | ||
); | ||
} | ||
|
||
function quorumNumbersRequired(string memory configData) internal pure returns (bytes memory) { | ||
return stdJson.readBytes(configData, ".initParams.eigenDA.thresholdRegistry.quorumNumbersRequired"); | ||
} | ||
|
||
function versionedBlobParams(string memory configData) internal pure returns (VersionedBlobParams[] memory) { | ||
bytes memory versionedBlobParamsRaw = | ||
stdJson.parseRaw(configData, ".initParams.eigenDA.thresholdRegistry.versionedBlobParams"); | ||
return abi.decode(versionedBlobParamsRaw, (VersionedBlobParams[])); | ||
} | ||
|
||
function batchConfirmers(string memory configData) internal pure returns (address[] memory) { | ||
return stdJson.readAddressArray(configData, ".initParams.eigenDA.serviceManager.batchConfirmers"); | ||
} | ||
|
||
function getCalldataInitParams(string memory configData) internal pure returns (CalldataInitParams memory) { | ||
return CalldataInitParams({ | ||
registryCoordinatorParams: CalldataRegistryCoordinatorParams({ | ||
operatorSetParams: operatorSetParams(configData), | ||
minimumStakes: minimumStakes(configData), | ||
strategyParams: strategyParams(configData) | ||
}), | ||
thresholdRegistryParams: CalldataThresholdRegistryParams({ | ||
quorumAdversaryThresholdPercentages: quorumAdversaryThresholdPercentages(configData), | ||
quorumConfirmationThresholdPercentages: quorumConfirmationThresholdPercentages(configData), | ||
quorumNumbersRequired: quorumNumbersRequired(configData), | ||
versionedBlobParams: versionedBlobParams(configData) | ||
}), | ||
serviceManagerParams: CalldataServiceManagerParams({batchConfirmers: batchConfirmers(configData)}) | ||
registryCoordinatorParams: cfg.registryCoordinatorParams(), | ||
paymentVaultParams: cfg.paymentVaultParams(), | ||
serviceManagerParams: cfg.serviceManagerParams() | ||
}); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just to learn - how does
console2
differ from just regularconsole
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the foundry doc,
"console2.sol contains patches to console.sol that allow Forge to decode traces for calls to the console, but it is not compatible with Hardhat."