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
Merged
2 changes: 2 additions & 0 deletions .github/workflows/run-scenarios.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ name: Run Scenarios
on:
workflow_dispatch:
pull_request:
permissions:
checks: write
jobs:
run-scenarios:
strategy:
Expand Down
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
63 changes: 63 additions & 0 deletions forge/script/marketupdates/ComputeContractsAddresses.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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.calculateContractAddresses(
salt,
msg.sender,
chainAddresses.marketAdmin,
chainAddresses.marketUpdatePauseGuardian,
chainAddresses.marketUpdateProposalGuardian,
chainAddresses.governorTimelockAddress
);

/// 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();
}
}
2 changes: 1 addition & 1 deletion forge/script/marketupdates/DeployContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ 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,
Expand Down
182 changes: 139 additions & 43 deletions forge/script/marketupdates/helpers/MarketUpdateContractsDeployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ 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,
Expand All @@ -57,33 +57,141 @@ library MarketUpdateContractsDeployer {
return deployedContracts;
}

function _deployContracts(
function _prepareAndDeployContracts(
bytes32 salt,
address msgSender,
address marketUpdateMultiSig,
address marketAdminPauseGuardianAddress,
address marketUpdateProposalGuardianAddress,
address localTimelockAddress
) 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 and deploy MarketUpdateTimelock
ContractDeploymentParams memory marketUpdateTimelockParams = getMarketUpdateTimelockParams(msgSender);

computedMarketUpdateTimelockAddress = computeContractAddress(create2Deployer, salt, marketUpdateTimelockParams);

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 = getMarketUpdateProposerParams(msgSender, marketUpdateMultiSig, marketUpdateProposalGuardianAddress, computedMarketUpdateTimelockAddress);

computedMarketUpdateProposerAddress = computeContractAddress(create2Deployer, salt, marketUpdateProposerParams);

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 = getConfiguratorParams();

computedConfiguratorAddress = computeContractAddress(create2Deployer, salt, configuratorParams);

deployContractWithCreate2(create2Deployer, salt, configuratorParams);
// No post-deployment actions

// Prepare and deploy MarketAdminPermissionChecker
ContractDeploymentParams memory marketAdminPermissionCheckerParams = getMarketAdminPermissionCheckerParams(msgSender);

computedMarketAdminPermissionCheckerAddress = computeContractAddress(create2Deployer, salt, marketAdminPermissionCheckerParams);

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 = getCometProxyAdminParams(msgSender);

computedCometProxyAdminAddress = computeContractAddress(create2Deployer, salt, cometProxyAdminParams);


deployContractWithCreate2(create2Deployer, salt, cometProxyAdminParams);

// Post-deployment actions
CometProxyAdmin(computedCometProxyAdminAddress).setMarketAdminPermissionChecker(MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress));
CometProxyAdmin(computedCometProxyAdminAddress).transferOwnership(localTimelockAddress);

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


return DeployedContracts({
marketUpdateTimelock: computedMarketUpdateTimelockAddress,
marketUpdateProposer: computedMarketUpdateProposerAddress,
newCometProxyAdmin: computedCometProxyAdminAddress,
newConfiguratorImplementation: computedConfiguratorAddress,
marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress
});
}

function calculateContractAddresses(
bytes32 salt,
address msgSender,
address marketUpdateMultiSig,
address marketAdminPauseGuardianAddress,
address marketUpdateProposalGuardianAddress,
address localTimelockAddress
) internal returns (DeployedContracts memory) {

ICreate2Deployer create2Deployer = ICreate2Deployer(create2DeployerAddress);
ContractDeploymentParams memory marketUpdateTimelockParams = getMarketUpdateTimelockParams(msgSender);

address computedMarketUpdateTimelockAddress = computeContractAddress(create2Deployer, salt, marketUpdateTimelockParams);
ContractDeploymentParams memory marketUpdateProposerParams = getMarketUpdateProposerParams(msgSender, marketUpdateMultiSig, marketUpdateProposalGuardianAddress, computedMarketUpdateTimelockAddress);

address computedMarketUpdateProposerAddress = computeContractAddress(create2Deployer, salt, marketUpdateProposerParams);
ContractDeploymentParams memory configuratorParams = getConfiguratorParams();

// Prepare deployment parameters for each contract
ContractDeploymentParams memory marketUpdateTimelockParams = ContractDeploymentParams({
address computedConfiguratorAddress = computeContractAddress(create2Deployer, salt, configuratorParams);
ContractDeploymentParams memory marketAdminPermissionCheckerParams = getMarketAdminPermissionCheckerParams(msgSender);

address computedMarketAdminPermissionCheckerAddress = computeContractAddress(create2Deployer, salt, marketAdminPermissionCheckerParams);

ContractDeploymentParams memory cometProxyAdminParams = getCometProxyAdminParams(msgSender);
address computedCometProxyAdminAddress = computeContractAddress(create2Deployer, salt, cometProxyAdminParams);

return DeployedContracts({
marketUpdateTimelock: computedMarketUpdateTimelockAddress,
marketUpdateProposer: computedMarketUpdateProposerAddress,
newCometProxyAdmin: computedCometProxyAdminAddress,
newConfiguratorImplementation: computedConfiguratorAddress,
marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress
});
}


function getMarketUpdateTimelockParams(address msgSender) internal pure returns (ContractDeploymentParams memory) {
return 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);

console.log("Current Governor of timelock", MarketUpdateTimelock(payable(computedMarketUpdateTimelockAddress)).governor());

ContractDeploymentParams memory marketUpdateProposerParams = ContractDeploymentParams({
function getMarketUpdateProposerParams(address msgSender, address marketUpdateMultiSig, address marketUpdateProposalGuardianAddress, address computedMarketUpdateTimelockAddress) internal pure returns (ContractDeploymentParams memory) {
return ContractDeploymentParams({
creationCode: type(MarketUpdateProposer).creationCode,
constructorArgs: abi.encode(
msgSender,
Expand All @@ -94,70 +202,58 @@ library MarketUpdateContractsDeployer {
expectedRuntimeCode: type(MarketUpdateProposer).runtimeCode,
contractName: "MarketUpdateProposer"
});
}

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

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

ContractDeploymentParams memory configuratorParams = ContractDeploymentParams({
function getConfiguratorParams() internal pure returns (ContractDeploymentParams memory) {
return ContractDeploymentParams({
creationCode: type(Configurator).creationCode,
constructorArgs: "",
expectedRuntimeCode: type(Configurator).runtimeCode,
contractName: "Configurator"
});
}

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

ContractDeploymentParams memory marketAdminPermissionCheckerParams = ContractDeploymentParams({
function getMarketAdminPermissionCheckerParams(address msgSender) internal pure returns (ContractDeploymentParams memory) {
return 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);

MarketAdminPermissionChecker(computedMarketAdminPermissionCheckerAddress).transferOwnership(localTimelockAddress);

ContractDeploymentParams memory cometProxyAdminParams = ContractDeploymentParams({
function getCometProxyAdminParams(address msgSender) internal pure returns (ContractDeploymentParams memory) {
return 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);

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

return DeployedContracts({
marketUpdateTimelock: computedMarketUpdateTimelockAddress,
marketUpdateProposer: computedMarketUpdateProposerAddress,
newCometProxyAdmin: computedCometProxyAdminAddress,
newConfiguratorImplementation: computedConfiguratorAddress,
marketAdminPermissionChecker: computedMarketAdminPermissionCheckerAddress
});
}


function deployContractWithCreate2(
ICreate2Deployer create2Deployer,
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
4 changes: 3 additions & 1 deletion plugins/scenario/utils/TokenSourcer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface SourceTokenParameters {
asset: string;
address: string;
blacklist: string[];
blockNumber?: number;
}

export async function fetchQuery(
Expand Down Expand Up @@ -55,14 +56,15 @@ export async function sourceTokens({
asset,
address,
blacklist,
blockNumber,
}: SourceTokenParameters) {
let amount = BigNumber.from(amount_);
if (amount.isZero()) {
return;
} else if (amount.isNegative()) {
await removeTokens(dm, amount.abs(), asset, address);
} else {
await addTokens(dm, amount, asset, address, [address].concat(blacklist));
await addTokens(dm, amount, asset, address, [address].concat(blacklist), blockNumber);
}
}

Expand Down
7 changes: 6 additions & 1 deletion scenario/RewardsScenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,12 @@ async function testScalingReward(properties: CometProperties, context: CometCont
[albert.address]
);
await newRewards.connect(albert.signer).setRewardConfigWithMultiplier(comet.address, rewardTokenAddress, multiplier);
await context.sourceTokens(exp(1_000, rewardDecimals), rewardTokenAddress, newRewards.address);
await context.sourceTokens(
100000, // maximum amount which can be sourced from transaction logs
rewardTokenAddress, // CometAsset
newRewards.address, // Recipient's address
2751700 // Block number to start searching for transfer event
);

await baseAsset.approve(albert, comet.address);
await albert.safeSupplyAsset({ asset: baseAssetAddress, amount: 100n * baseScale });
Expand Down
Loading
Loading