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

added a script for computing contract addresses #48

Merged
merged 10 commits into from
Oct 21, 2024
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ deploy-contracts:
-vvvv \
--sender $(SENDER)

# Compute contracts addresses
compute-contracts-addresses:
@echo "Computing contracts addresses..."
CHAIN_ID=$(CHAIN_ID) forge script forge/script/marketupdates/ComputeContractsAddresses.s.sol:ComputeContractAddresses \
--rpc-url $(RPC_URL) \
--optimize \
--optimizer-runs 200 \
--use $(SOLIDITY_COMPILER_VERSION) \
--evm-version $(EVM_VERSION) \
--via-ir \
-vvvv \
--skip-simulation \
--sender $(SENDER)

# Verifying MarketUpdateTimelock
verify-MarketUpdateTimelock:
@echo "Verifying MarketUpdateTimelock..."
Expand Down
64 changes: 64 additions & 0 deletions forge/script/marketupdates/ComputeContractsAddresses.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@forge-std/src/Script.sol";
import "@forge-std/src/console.sol";
import "@comet-contracts/marketupdates/MarketUpdateTimelock.sol";
import "@comet-contracts/marketupdates/MarketUpdateProposer.sol";
import "@comet-contracts/Configurator.sol";
import "@comet-contracts/CometProxyAdmin.sol";
import "@comet-contracts/marketupdates/MarketAdminPermissionChecker.sol";
import "@comet-contracts/Create2DeployerInterface.sol";
import "./helpers/MarketUpdateAddresses.sol";
import "./helpers/MarketUpdateContractsDeployer.sol";
import "./helpers/ChainAddresses.sol";

contract ComputeContractAddresses is Script {
address public deployedWalletAddress;

address constant public create2DeployerAddress = 0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2;

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: compound.solidity.constant-not-in-uppercase Note

A constant name is not in UPPER_CASE like other constant variables.
address constant public ZER0_ADDRESS_MARKET_UPDATE_PROPOSAL_GUARDIAN = address(0);
address constant public ZER0_ADDRESS_MARKET_ADMIN_PAUSE_GUARDIAN = address(0);
address constant public INITIAL_ADDRESS_MARKET_UPDATE_MULTI_SIG = address(0x7e14050080306cd36b47DE61ce604b3a1EC70c4e);


function run() external {
uint256 passedChainId = vm.envUint("CHAIN_ID");

require(block.chainid == passedChainId, "Chain ID mismatch");

Check notice

Code scanning / Semgrep OSS

Semgrep Finding: rules.solidity.performance.use-custom-error-not-require Note

Consider using custom errors as they are more gas efficient while allowing developers
to describe the error in detail using NatSpec.

ChainAddresses.Chain chain = ChainAddresses.getChainBasedOnChainId(passedChainId);
ChainAddresses.ChainAddressesStruct memory chainAddresses = ChainAddresses.getChainAddresses(chain);

console.log("Deploying contracts with sender: ", msg.sender);

uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");

address deployer = vm.rememberKey(deployerPrivateKey);
vm.startBroadcast(deployer);

console.log("Broadcasting transaction with deployer: ", deployer);

bytes32 salt = keccak256(abi.encodePacked(vm.envString("SALT")));

/// Call library function
MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer._prepareAndDeployContracts(
salt,
msg.sender,
chainAddresses.marketAdmin,
chainAddresses.marketUpdatePauseGuardian,
chainAddresses.marketUpdateProposalGuardian,
chainAddresses.governorTimelockAddress,
false // deploy flag set to false
);

/// Console log deployed contracts
console.log("MarketUpdateTimelock: ", deployedContracts.marketUpdateTimelock);
console.log("MarketUpdateProposer: ", deployedContracts.marketUpdateProposer);
console.log("NewConfiguratorImplementation: ", deployedContracts.newConfiguratorImplementation);
console.log("NewCometProxyAdmin: ", deployedContracts.newCometProxyAdmin);
console.log("MarketAdminPermissionChecker: ", deployedContracts.marketAdminPermissionChecker);

vm.stopBroadcast();
}
}
5 changes: 3 additions & 2 deletions forge/script/marketupdates/DeployContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ contract DeployContracts is Script {
bytes32 salt = keccak256(abi.encodePacked(vm.envString("SALT")));

/// Call library function
MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer._deployContracts(
MarketUpdateContractsDeployer.DeployedContracts memory deployedContracts = MarketUpdateContractsDeployer._prepareAndDeployContracts(
salt,
msg.sender,
chainAddresses.marketAdmin,
chainAddresses.marketUpdatePauseGuardian,
chainAddresses.marketUpdateProposalGuardian,
chainAddresses.governorTimelockAddress
chainAddresses.governorTimelockAddress,
true // deploy flag set to true
);

/// Console log deployed contracts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,45 +44,57 @@ library MarketUpdateContractsDeployer {
console.log("Deploying contracts with sender", msg.sender);
vm.startBroadcast(msg.sender);

DeployedContracts memory deployedContracts = _deployContracts(
DeployedContracts memory deployedContracts = _prepareAndDeployContracts(
salt,
msg.sender,
marketUpdateMultiSig,
marketAdminPauseGuardianAddress,
marketUpdateProposalGuardianAddress,
localTimelockAddress
localTimelockAddress,
true // deploy flag set to true
);

vm.stopBroadcast();
return deployedContracts;
}

function _deployContracts(
function _prepareAndDeployContracts(
bytes32 salt,
address msgSender,
address marketUpdateMultiSig,
address marketAdminPauseGuardianAddress,
address marketUpdateProposalGuardianAddress,
address localTimelockAddress
address localTimelockAddress,
bool deploy
) internal returns (DeployedContracts memory) {
console.log("Deploying contracts with sender", msgSender);

console.log("Preparing contracts with sender", msgSender);

ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress);

// Initialize variables to hold computed addresses
address computedMarketUpdateTimelockAddress;
address computedMarketUpdateProposerAddress;
address computedConfiguratorAddress;
address computedMarketAdminPermissionCheckerAddress;
address computedCometProxyAdminAddress;

// Prepare deployment parameters for each contract
// Prepare and deploy MarketUpdateTimelock
ContractDeploymentParams memory marketUpdateTimelockParams = ContractDeploymentParams({
creationCode: type(MarketUpdateTimelock).creationCode,
constructorArgs: abi.encode(msgSender, 2 days), // 2 days
constructorArgs: abi.encode(msgSender, 2 days),
expectedRuntimeCode: type(MarketUpdateTimelock).runtimeCode,
contractName: "MarketUpdateTimelock"
});

address computedMarketUpdateTimelockAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateTimelockParams);
computedMarketUpdateTimelockAddress = computeContractAddress(create2Deployer, salt, marketUpdateTimelockParams);

console.log("Current Governor of timelock", MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).governor());
if (deploy) {
deployContractWithCreate2(create2Deployer, salt, marketUpdateTimelockParams);
// Perform any post-deployment actions
console.log("Current Governor of timelock", MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).governor());
}

// Prepare and deploy MarketUpdateProposer
ContractDeploymentParams memory marketUpdateProposerParams = ContractDeploymentParams({
creationCode: type(MarketUpdateProposer).creationCode,
constructorArgs: abi.encode(
Expand All @@ -95,48 +107,73 @@ library MarketUpdateContractsDeployer {
contractName: "MarketUpdateProposer"
});

address computedMarketUpdateProposerAddress = deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams);
MarketUpdateProposer(computedMarketUpdateProposerAddress).setMarketAdmin(marketUpdateMultiSig);
MarketUpdateProposer(computedMarketUpdateProposerAddress).setProposalGuardian(marketUpdateProposalGuardianAddress);
MarketUpdateProposer(computedMarketUpdateProposerAddress).setGovernor(localTimelockAddress);
computedMarketUpdateProposerAddress = computeContractAddress(create2Deployer, salt, marketUpdateProposerParams);

MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setMarketUpdateProposer(computedMarketUpdateProposerAddress);
MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setGovernor(localTimelockAddress);
if (deploy) {
deployContractWithCreate2(create2Deployer, salt, marketUpdateProposerParams);

// Post-deployment actions
MarketUpdateProposer(computedMarketUpdateProposerAddress).setMarketAdmin(marketUpdateMultiSig);
MarketUpdateProposer(computedMarketUpdateProposerAddress).setProposalGuardian(marketUpdateProposalGuardianAddress);
MarketUpdateProposer(computedMarketUpdateProposerAddress).setGovernor(localTimelockAddress);

MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setMarketUpdateProposer(computedMarketUpdateProposerAddress);
MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).setGovernor(localTimelockAddress);
}

// Prepare and deploy Configurator
ContractDeploymentParams memory configuratorParams = ContractDeploymentParams({
creationCode: type(Configurator).creationCode,
constructorArgs: "",
expectedRuntimeCode: type(Configurator).runtimeCode,
contractName: "Configurator"
});

address computedConfiguratorAddress = deployContractWithCreate2(create2Deployer, salt, configuratorParams);
computedConfiguratorAddress = computeContractAddress(create2Deployer, salt, configuratorParams);

if (deploy) {
deployContractWithCreate2(create2Deployer, salt, configuratorParams);
// No post-deployment actions
}

// Prepare and deploy MarketAdminPermissionChecker
ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({
creationCode: type(MarketAdminPermissionChecker).creationCode,
constructorArgs: abi.encode(msgSender, INITIAL_ADDRESS_MARKET_UPDATE_MULTI_SIG, address(0)),
expectedRuntimeCode: type(MarketAdminPermissionChecker).runtimeCode,
contractName: "MarketAdminPermissionChecker"
});

address computedMarketAdminPermissionCheckerAddress = deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams);
MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdmin(computedMarketUpdateTimelockAddress);
MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdminPauseGuardian(marketAdminPauseGuardianAddress);
computedMarketAdminPermissionCheckerAddress = computeContractAddress(create2Deployer, salt, marketAdminPermissionCheckerParams);

MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress);
if (deploy) {
deployContractWithCreate2(create2Deployer, salt, marketAdminPermissionCheckerParams);

// Post-deployment actions
MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdmin(computedMarketUpdateTimelockAddress);
MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).setMarketAdminPauseGuardian(marketAdminPauseGuardianAddress);
MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress);
}

// Prepare and deploy CometProxyAdmin
ContractDeploymentParams memory cometProxyAdminParams = ContractDeploymentParams({
creationCode: type(CometProxyAdmin).creationCode,
constructorArgs: abi.encode(msgSender),
expectedRuntimeCode: type(CometProxyAdmin).runtimeCode,
contractName: "CometProxyAdmin"
});

address computedCometProxyAdminAddress = deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams);
CometProxyAdmin(computedCometProxyAdminAddress).setMarketAdminPermissionChecker(MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress));
CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress);
computedCometProxyAdminAddress = computeContractAddress(create2Deployer, salt, cometProxyAdminParams);

if (deploy) {
deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams);

console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner());
// Post-deployment actions
CometProxyAdmin(computedCometProxyAdminAddress).setMarketAdminPermissionChecker(MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress));
CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress);

console.log("Owner of cometProxyAdmin: ", CometProxyAdmin(computedCometProxyAdminAddress).owner());
}

return DeployedContracts({
marketUpdateTimelock: computedMarketUpdateTimelockAddress,
Expand All @@ -152,12 +189,22 @@ library MarketUpdateContractsDeployer {
bytes32 salt,
ContractDeploymentParams memory params
) internal returns (address) {
address computedAddress = computeContractAddress(create2Deployer, salt, params);
bytes memory bytecode = abi.encodePacked(params.creationCode, params.constructorArgs);
address computedAddress = create2Deployer.computeAddress(salt, keccak256(bytecode));
checkOrDeployAndCompareBytecodes(create2Deployer, salt, bytecode, computedAddress, params.expectedRuntimeCode);
return computedAddress;
}

function computeContractAddress(
ICreate2Deployer create2Deployer,
bytes32 salt,
ContractDeploymentParams memory params
) internal view returns (address) {
bytes memory bytecode = abi.encodePacked(params.creationCode, params.constructorArgs);
address computedAddress = create2Deployer.computeAddress(salt, keccak256(bytecode));
return computedAddress;
}

function checkOrDeployAndCompareBytecodes(
ICreate2Deployer create2Deployer,
bytes32 salt,
Expand Down
2 changes: 1 addition & 1 deletion src/deploy/Network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export async function deployNetworkComet(
const cometAdmin = await deploymentManager.deploy(
'cometAdmin',
'CometProxyAdmin.sol',
[],
[governor],
maybeForce()
);

Expand Down
Loading