Skip to content

Commit

Permalink
Merge branch 'release/core-contracts/12' into feat/epoch-manager
Browse files Browse the repository at this point in the history
  • Loading branch information
pahor167 committed Aug 19, 2024
2 parents 973c21e + 533ccd1 commit efebfb7
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 84 deletions.
8 changes: 8 additions & 0 deletions packages/protocol/contracts-0.8/common/UsingRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import "../../contracts/stability/interfaces/ISortedOracles.sol";
import "../../contracts/common/interfaces/IFeeCurrencyWhitelist.sol";
import "./interfaces/IScoreReader.sol";

import "../../contracts/governance/interfaces/IElection.sol";
import "../../contracts/common/interfaces/IFeeHandlerSeller.sol";
import "../../contracts/governance/interfaces/IEpochRewards.sol";

contract UsingRegistry is Ownable {
// solhint-disable state-visibility
Expand All @@ -33,6 +35,7 @@ contract UsingRegistry is Ownable {
bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID =
keccak256(abi.encodePacked("DoubleSigningSlasher"));
bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election"));
bytes32 constant EPOCH_REWARDS_REGISTRY_ID = keccak256(abi.encodePacked("EpochRewards"));
bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange"));
bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID =
keccak256(abi.encodePacked("FeeCurrencyWhitelist"));
Expand Down Expand Up @@ -130,6 +133,11 @@ contract UsingRegistry is Ownable {
function getElection() internal view returns (IElection) {
return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID));
}

function getEpochRewards() internal view returns (IEpochRewards) {
return IEpochRewards(registry.getAddressForOrDie(EPOCH_REWARDS_REGISTRY_ID));
}

function getGovernance() internal view returns (IGovernance) {
return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID));
}
Expand Down
34 changes: 17 additions & 17 deletions packages/protocol/migrations_sol/Migration.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ contract ForceTx {
contract Migration is Script, UsingRegistry, MigrationsConstants {
using stdJson for string;

// This is Anvil's default account
address constant deployerAccount = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266;

IProxyFactory proxyFactory;

uint256 proxyNonce = 0;
Expand Down Expand Up @@ -188,8 +185,8 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
* Entry point of the script
*/
function run() external {
// TODO check that this matches deployerAccount and the pK can be avoided with --unlock
vm.startBroadcast(deployerAccount);
// TODO check that this matches DEPLOYER_ACCOUNT and the pK can be avoided with --unlock
vm.startBroadcast(DEPLOYER_ACCOUNT);

string memory json = vm.readFile("./migrations_sol/migrationsConfig.json");

Expand All @@ -199,12 +196,7 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {

// Proxy for Registry is already set, just deploy implementation
migrateRegistry();

// Foloowing lines required by parent UsingRegistry
_transferOwnership(deployerAccount);
setRegistry(REGISTRY_ADDRESS);

// End UsingRegistry setup
setupUsingRegistry();

migrateFreezer();
migrateFeeCurrencyWhitelist();
Expand Down Expand Up @@ -245,6 +237,14 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
electValidators(json);
}

/**
* The function calls defined here are required by the parent UsingRegistry.sol contract.
*/
function setupUsingRegistry() public {
_transferOwnership(DEPLOYER_ACCOUNT);
setRegistry(REGISTRY_ADDRESS);
}

function migrateRegistry() public {
setImplementationOnProxy(
IProxy(REGISTRY_ADDRESS),
Expand Down Expand Up @@ -333,7 +333,7 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {

function migrateReserveSpenderMultiSig(string memory json) public {
address[] memory owners = new address[](1);
owners[0] = deployerAccount;
owners[0] = DEPLOYER_ACCOUNT;

uint256 required = abi.decode(json.parseRaw(".reserveSpenderMultiSig.required"), (uint256));
uint256 internalRequired = abi.decode(
Expand Down Expand Up @@ -402,7 +402,7 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
bool useSpender = abi.decode(json.parseRaw(".reserveSpenderMultiSig.required"), (bool));
address spender = useSpender
? registry.getAddressForString("ReserveSpenderMultiSig")
: deployerAccount;
: DEPLOYER_ACCOUNT;

IReserve(reserveProxyAddress).addSpender(spender);
console.log("reserveSpenderMultiSig added as Reserve spender");
Expand Down Expand Up @@ -442,7 +442,7 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
}

// TODO add more configurable oracles from the json
getSortedOracles().addOracle(stableTokenProxyAddress, deployerAccount);
getSortedOracles().addOracle(stableTokenProxyAddress, DEPLOYER_ACCOUNT);

if (celoPrice != 0) {
console.log("before report");
Expand Down Expand Up @@ -488,7 +488,7 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {
uint256 celoPrice = abi.decode(json.parseRaw(".stableTokens.celoPrice"), (uint256));

address[] memory initialBalanceAddresses = new address[](1);
initialBalanceAddresses[0] = deployerAccount;
initialBalanceAddresses[0] = DEPLOYER_ACCOUNT;

uint256[] memory initialBalanceValues = new uint256[](1);
initialBalanceValues[0] = initialBalanceValue;
Expand Down Expand Up @@ -817,7 +817,7 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {

function migrateGovernanceApproverMultiSig(string memory json) public {
address[] memory owners = new address[](1);
owners[0] = deployerAccount;
owners[0] = DEPLOYER_ACCOUNT;

uint256 required = abi.decode(json.parseRaw(".governanceApproverMultiSig.required"), (uint256));
uint256 internalRequired = abi.decode(
Expand Down Expand Up @@ -925,7 +925,7 @@ contract Migration is Script, UsingRegistry, MigrationsConstants {

address approver = useApprover
? registry.getAddressForString("GovernanceApproverMultiSig")
: deployerAccount;
: DEPLOYER_ACCOUNT;
uint256 concurrentProposals = abi.decode(
json.parseRaw(".governance.concurrentProposals"),
(uint256)
Expand Down
42 changes: 42 additions & 0 deletions packages/protocol/migrations_sol/MigrationL2.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
pragma solidity >=0.8.7 <0.8.20;

import { Script } from "forge-std-8/Script.sol";
import { MigrationsConstants } from "@migrations-sol/constants.sol";

import "@celo-contracts/common/FixidityLib.sol";
import "@celo-contracts-8/common/UsingRegistry.sol";

contract MigrationL2 is Script, MigrationsConstants, UsingRegistry {
using FixidityLib for FixidityLib.Fraction;

/**
* Entry point of the script
*/
function run() external {
vm.startBroadcast(DEPLOYER_ACCOUNT);

setupUsingRegistry();
activateCeloDistributionSchedule();

vm.stopBroadcast();
}

function setupUsingRegistry() public {
_transferOwnership(DEPLOYER_ACCOUNT);
setRegistry(REGISTRY_ADDRESS);
}

function activateCeloDistributionSchedule() public {
uint256 l2StartTime = 1721909903 - 5; // Arbitrarily 5 seconds before last black
uint256 communityRewardFraction = getEpochRewards().getCommunityRewardFraction();
address carbonOffsettingPartner = 0x22579CA45eE22E2E16dDF72D955D6cf4c767B0eF;
uint256 carbonOffsettingFraction = getEpochRewards().getCarbonOffsettingFraction();

getCeloDistributionSchedule().activate(
l2StartTime,
communityRewardFraction,
carbonOffsettingPartner,
carbonOffsettingFraction
);
}
}
3 changes: 3 additions & 0 deletions packages/protocol/migrations_sol/constants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ pragma solidity >=0.8.7 <0.8.20;
import { TestConstants } from "@test-sol/constants.sol";

contract MigrationsConstants is TestConstants {
// Addresses
address constant DEPLOYER_ACCOUNT = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266;

// List of contracts that are expected to be in Registry.sol
string[24] contractsInRegistry = [
"Accounts",
Expand Down
6 changes: 3 additions & 3 deletions packages/protocol/scripts/foundry/constants.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# Anvil accounts
export FROM_ACCOUNT_NO_ZERO="f39Fd6e51aad88F6F4ce6aB8827279cffFb92266" # Anvil default account (1)
export FROM_ACCOUNT="0x$FROM_ACCOUNT_NO_ZERO" # Anvil default account (1)
export FROM_ACCOUNT_PRIVATE_KEY_NO_ZERO="ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" # Anvil default account (1)
export FROM_ACCOUNT_PRIVATE_KEY="0x$FROM_ACCOUNT_PRIVATE_KEY_NO_ZERO" # Anvil default account (1)

# Anvil configurations (Source: https://book.getfoundry.sh/reference/anvil/)
export ANVIL_PORT=8546
Expand All @@ -15,7 +13,9 @@ export STEPS_TRACING="--steps-tracing" # Steps tracing used for debug calls ret

# Forge migration script configurations (Source: https://book.getfoundry.sh/reference/forge/forge-script)
export MIGRATION_SCRIPT_PATH="migrations_sol/Migration.s.sol" # Path to migration script
export TARGET_CONTRACT="Migration" # The name of the contract you want to run.
export MIGRATION_L2_SCRIPT_PATH="migrations_sol/MigrationL2.s.sol" # Path to L2 migration script
export MIGRATION_TARGET_CONTRACT="Migration" # The name of the contract you want to run.
export MIGRATION_L2_TARGET_CONTRACT="MigrationL2" # The name of the contract you want to run.
export BROADCAST="--broadcast" # Broadcasts the transactions. Enable: "--broadcast" / Disable: ""
export SKIP_SIMULATION="" # Skips on-chain simulation. Enable: "--skip-simulation" / Disable: ""
export NON_INTERACTIVE="--non-interactive" # Remove interactive prompts which appear if the contract is near the EIP-170 size limit.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ $REGISTRY_ADDRESS $REGISTRY_STORAGE_LOCATION "0x000000000000000000000000$REGISTR
# Run migrations
echo "Running migration script... "
forge script \
$MIGRATION_SCRIPT_PATH \
--target-contract $TARGET_CONTRACT \
--sender $FROM_ACCOUNT \
--unlocked \
$VERBOSITY_LEVEL \
$BROADCAST \
$SKIP_SIMULATION \
$NON_INTERACTIVE \
$LIBRARY_FLAGS \
--rpc-url $ANVIL_RPC_URL || echo "Migration script failed"
$MIGRATION_SCRIPT_PATH \
--target-contract $MIGRATION_TARGET_CONTRACT \
--sender $FROM_ACCOUNT \
--unlocked \
$VERBOSITY_LEVEL \
$BROADCAST \
$SKIP_SIMULATION \
$NON_INTERACTIVE \
$LIBRARY_FLAGS \
--rpc-url $ANVIL_RPC_URL || echo "Migration script failed"

# Keeping track of the finish time to measure how long it takes to run the script entirely
ELAPSED_TIME=$(($SECONDS - $START_TIME))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,71 +8,54 @@ source $PWD/scripts/foundry/constants.sh
echo "Generating and running L1 devchain before activating L2..."
source $PWD/scripts/foundry/create_and_migrate_anvil_devchain.sh

# Stop L1 devchain
source $PWD/scripts/foundry/stop_anvil.sh
# Backup L1 state before applying L2 migrations so it can be published to NPM
cp $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME $TMP_FOLDER/backup_$L1_DEVCHAIN_FILE_NAME

# Duplicate L1 state
cp $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME $TMP_FOLDER/$L2_DEVCHAIN_FILE_NAME

# Start L2 devchain from L1 state and apply L2 migrations
echo "Anvil L2 state will be saved to $TMP_FOLDER/$L2_DEVCHAIN_FILE_NAME"
anvil \
--port $ANVIL_PORT \
--state $TMP_FOLDER/$L2_DEVCHAIN_FILE_NAME \
--state-interval $STATE_INTERVAL \
--gas-limit $GAS_LIMIT \
--code-size-limit $CODE_SIZE_LIMIT \
--balance $BALANCE \
--steps-tracing &

# Activate the L2 on the devchain by deploying arbitrary bytecode to the PROXY_ADMIN_ADDRESS
# Arbitrarily using Registry.sol bytcode, but we could have used any
# other arbitary bytecode of length > 0. See `isL2()` implementation in IsL2Check.sol.
echo "Activating L2 on the devchain..."
REGISTRY_BYTECODE=$(jq -r '.bytecode.object' ./out/Registry.sol/Registry.json)
# Activate L2 by deploying arbitrary bytecode to the proxy admin address.
# Note: This can't be done from the migration script
ARBITRARY_BYTECODE=$(cast format-bytes32-string "L2 is activated")
cast rpc anvil_setCode \
$PROXY_ADMIN_ADDRESS \
$REGISTRY_BYTECODE \
--rpc-url $ANVIL_RPC_URL
$PROXY_ADMIN_ADDRESS $ARBITRARY_BYTECODE \
--rpc-url $ANVIL_RPC_URL

# Fetch address of Celo distribution
CELO_DISTRIBUTION_SCHEDULE_ADDRESS=$(
cast call \
$REGISTRY_ADDRESS \
"getAddressForStringOrDie(string calldata identifier)(address)" \
"CeloDistributionSchedule" \
--rpc-url $ANVIL_RPC_URL
$REGISTRY_ADDRESS \
"getAddressForStringOrDie(string calldata identifier)(address)" \
"CeloDistributionSchedule" \
--rpc-url $ANVIL_RPC_URL
)

# Set the balance of the CeloDistributionSchedule (like the Celo client would do during L2 genesis)
# This cannot be done during the migrations, because CeloDistributionSchedule.sol does not
# implement the receive function nor does it allow ERC20 transfers.
# This is the only way I managed to give the CeloDistributionSchedule a balance.
# Note: This can't be done from the migration script, because CeloDistributionSchedule.sol does not
# implement the receive function nor does it allow ERC20 transfers. This is the only way I
# managed to give the CeloDistributionSchedule a balance.
echo "Setting CeloDistributionSchedule balance..."
cast rpc \
anvil_setBalance \
$CELO_DISTRIBUTION_SCHEDULE_ADDRESS $CELO_DISTRIBUTION_SCHEDULE_INITIAL_BALANCE \
--rpc-url $ANVIL_RPC_URL
anvil_setBalance \
$CELO_DISTRIBUTION_SCHEDULE_ADDRESS $CELO_DISTRIBUTION_SCHEDULE_INITIAL_BALANCE \
--rpc-url $ANVIL_RPC_URL

# Fetch timestamp of the latest block
LATEST_BLOCK_TIMESTAMP=$(
cast block \
latest \
--field timestamp \
--rpc-url $ANVIL_RPC_URL
)
# Run L2 migrations
echo "Running L2 migration script... "
forge script \
$MIGRATION_L2_SCRIPT_PATH \
--target-contract $MIGRATION_L2_TARGET_CONTRACT \
--sender $FROM_ACCOUNT \
--unlocked \
$VERBOSITY_LEVEL \
$BROADCAST \
$SKIP_SIMULATION \
$NON_INTERACTIVE \
--rpc-url $ANVIL_RPC_URL || echo "L2 Migration script failed"

# Save L2 state so it can published to NPM
cp $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME $TMP_FOLDER/$L2_DEVCHAIN_FILE_NAME
echo "Saved anvil L2 state to $TMP_FOLDER/$L2_DEVCHAIN_FILE_NAME"

# Arbitrarily set L2 start time at 5 seconds before the latest block. The L2 start time can be any
# timestamp in the past, but can never be in the future.
L2_START_TIME=$((LATEST_BLOCK_TIMESTAMP - 5))
# Restore L1 state from backup so it can be published to NPM as well
cp $TMP_FOLDER/backup_$L1_DEVCHAIN_FILE_NAME $TMP_FOLDER/$L1_DEVCHAIN_FILE_NAME

# Activate CeloDistributionSchedule
echo "Activating CeloDistributionSchedule..."
cast send \
$CELO_DISTRIBUTION_SCHEDULE_ADDRESS \
"activate(uint256,uint256,address,uint256)" \
$L2_START_TIME $COMMUNITY_REWARD_FRACTION $CARBON_OFFSETTING_PARTNER $CARBON_OFFSETTING_FRACTION \
--from $FROM_ACCOUNT \
--private-key $FROM_ACCOUNT_PRIVATE_KEY \
--gas-limit 10000000 \
--rpc-url $ANVIL_RPC_URL
# Delete backup
rm $TMP_FOLDER/backup_$L1_DEVCHAIN_FILE_NAME

0 comments on commit efebfb7

Please sign in to comment.