Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
[submodule "packages/contracts-bedrock/lib/safe-contracts"]
path = packages/contracts-bedrock/lib/safe-contracts
url = https://github.com/celo-org/safe-smart-account
branch = mc01/v1.4.0
branch = mc01/v1.3.0
[submodule "packages/contracts-bedrock/lib/kontrol-cheatcodes"]
path = packages/contracts-bedrock/lib/kontrol-cheatcodes
url = https://github.com/runtimeverification/kontrol-cheatcodes
Expand Down
11 changes: 11 additions & 0 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,16 @@ func (d *AltDADeployConfig) Check(log log.Logger) error {
return nil
}

type CeloDeployConfig struct {
DeployCeloContracts bool `json:"deployCeloContracts" toml:"deployCeloContracts"`
}

var _ ConfigChecker = (*CeloDeployConfig)(nil)

func (d *CeloDeployConfig) Check(log log.Logger) error {
return nil
}

// L2InitializationConfig represents all L2 configuration
// data that can be configured before the deployment of any L1 contracts.
type L2InitializationConfig struct {
Expand All @@ -672,6 +682,7 @@ type L2InitializationConfig struct {
UpgradeScheduleDeployConfig
L2CoreDeployConfig
AltDADeployConfig
CeloDeployConfig
}

func (d *L2InitializationConfig) Check(log log.Logger) error {
Expand Down
2 changes: 2 additions & 0 deletions op-deployer/pkg/deployer/opcm/implementations.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ type DeployImplementationsInput struct {
SuperchainProxyAdmin common.Address
UpgradeController common.Address
UseInterop bool // if true, deploy Interop implementations
// For Celo Kurtosis Devent
UseDevCeloTokenL1 bool // Deploy DevCeloTokenL1 instead of CeloTokenL1
}

func (input *DeployImplementationsInput) InputSet() bool {
Expand Down
6 changes: 6 additions & 0 deletions op-deployer/pkg/deployer/pipeline/implementations.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
return fmt.Errorf("error merging proof params from overrides: %w", err)
}

var useDevCeloTokenL1 bool
if shouldDeployDevCeloTokenL1, ok := intent.GlobalDeployOverrides["useDevCeloTokenL1"].(bool); ok {
useDevCeloTokenL1 = shouldDeployDevCeloTokenL1
}

dio, err := opcm.DeployImplementations(
env.L1ScriptHost,
opcm.DeployImplementationsInput{
Expand All @@ -59,6 +64,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
SuperchainProxyAdmin: st.SuperchainDeployment.ProxyAdminAddress,
UpgradeController: intent.SuperchainRoles.ProxyAdminOwner,
UseInterop: intent.UseInterop,
UseDevCeloTokenL1: useDevCeloTokenL1,
},
)
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions packages/contracts-bedrock/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ forge-build-dev *ARGS:
build-source:
forge build --skip "/**/test/**" --skip "/**/scripts/**"

# Builds source contracts and scripts, skipping tests.
build-no-tests:
forge build --skip "/**/test/**" --libraries \
"src/celo/common/linkedlists/AddressSortedLinkedListWithMedian.sol:AddressSortedLinkedListWithMedian:0xED477A99035d0c1e11369F1D7A4e587893cc002B"

# Builds the contracts.
build *ARGS: lint-fix-no-fail
just forge-build {{ARGS}}
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts-bedrock/lib/safe-contracts
Submodule safe-contracts updated 147 files
200 changes: 200 additions & 0 deletions packages/contracts-bedrock/scripts/L2Genesis.s.sol
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard to say something specific -> but I would compare this file with the one from martinvol/completeMigrations: https://github.com/celo-org/optimism/blob/martinvol/completeMigrations/packages/contracts-bedrock/scripts/L2Genesis.s.sol

And discuss potential differences with @martinvol -> since this one is the base for changes in Migration.s.sol

Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ import { IL2CrossDomainMessenger } from "interfaces/L2/IL2CrossDomainMessenger.s
import { IGasPriceOracle } from "interfaces/L2/IGasPriceOracle.sol";
import { IL1Block } from "interfaces/L2/IL1Block.sol";

// Celo Specific Contracts
import { GoldToken } from "src/celo/GoldToken.sol";
import { CeloPredeploys } from "src/celo/CeloPredeploys.sol";
import { CeloRegistry } from "src/celo/CeloRegistry.sol";
import { FeeHandler } from "src/celo/FeeHandler.sol";
import { MentoFeeHandlerSeller } from "src/celo/MentoFeeHandlerSeller.sol";
import { UniswapFeeHandlerSeller } from "src/celo/UniswapFeeHandlerSeller.sol";
import { SortedOracles } from "src/celo/stability/SortedOracles.sol";
import { FeeCurrencyDirectory } from "src/celo/FeeCurrencyDirectory.sol";
import { FeeCurrency } from "src/celo/testing/FeeCurrency.sol";
import { StableTokenV2 } from "src/celo/StableTokenV2.sol";
import { AddressSortedLinkedListWithMedian } from "src/celo/common/linkedlists/AddressSortedLinkedListWithMedian.sol";

struct L1Dependencies {
address payable l1CrossDomainMessengerProxy;
address payable l1StandardBridgeProxy;
Expand All @@ -54,6 +67,10 @@ contract L2Genesis is Deployer {

uint80 internal constant DEV_ACCOUNT_FUND_AMT = 10_000 ether;

// Define here to use mainnet fee currency directory address
// (CeloPredeploy's fee currency directory address is for Alfajores)
address internal constant FEE_CURRENCY_DIRECTORY = 0x15F344b9E6c3Cb6F0376A36A64928b13F62C6276;

/// @notice Default Anvil dev accounts. Only funded if `cfg.fundDevAccounts == true`.
/// Also known as "test test test test test test test test test test test junk" mnemonic accounts,
/// on path "m/44'/60'/0'/0/i" (where i is the account index).
Expand Down Expand Up @@ -158,6 +175,9 @@ contract L2Genesis is Deployer {
if (cfg.fundDevAccounts()) {
fundDevAccounts();
}
if (cfg.deployCeloContracts()) {
setCeloPredeploys();
}
vm.stopPrank();

if (writeForkGenesisAllocs(_fork, Fork.DELTA, _mode)) {
Expand Down Expand Up @@ -675,4 +695,184 @@ contract L2Genesis is Deployer {
vm.deal(devAccounts[i], DEV_ACCOUNT_FUND_AMT);
}
}

///@notice Sets all proxies and implementations for Celo contracts
function setCeloPredeploys() internal {
console.log("Deploying Celo contracts");

setCeloRegistry();
setCeloGoldToken();
setCeloFeeHandler();
setCeloMentoFeeHandlerSeller();
setCeloUniswapFeeHandlerSeller();
setCeloAddressSortedLinkedListWithMedian();
setCeloSortedOracles();
setCeloFeeCurrency();
setFeeCurrencyDirectory();

address[] memory initialBalanceAddresses = new address[](2);
initialBalanceAddresses[0] = devAccounts[0];
initialBalanceAddresses[1] = CeloPredeploys.FEE_HANDLER; // Seed the FeeHandler with a tiny balance to avoid the 20 000-gas “cold” SSTORE on its first transfer

uint256[] memory initialBalances = new uint256[](2);
initialBalances[0] = 100_000 ether;
initialBalances[1] = 1;
deploycUSD(initialBalanceAddresses, initialBalances, 2);
}

/// @notice Sets up a proxy for the given impl address
function _setupProxy(address addr, address impl) internal returns (address) {
bytes memory code = vm.getDeployedCode("Proxy.sol:Proxy");
vm.etch(addr, code);
EIP1967Helper.setAdmin(addr, Predeploys.PROXY_ADMIN);

console.log("Setting proxy %s with implementation: %s", addr, impl);
EIP1967Helper.setImplementation(addr, impl);

return addr;
}

function setCeloRegistry() internal {
CeloRegistry kontract = new CeloRegistry({ test: false });

address precompile = CeloPredeploys.CELO_REGISTRY;
string memory cname = CeloPredeploys.getName(precompile);
console.log("Deploying %s implementation at: %s", cname, address(kontract));

vm.resetNonce(address(kontract));
_setupProxy(precompile, address(kontract));
}

function setCeloGoldToken() internal {
GoldToken kontract = new GoldToken({ test: false });

address precompile = CeloPredeploys.GOLD_TOKEN;
string memory cname = CeloPredeploys.getName(precompile);
console.log("Deploying %s implementation at: %s", cname, address(kontract));

vm.resetNonce(address(kontract));
_setupProxy(precompile, address(kontract));
}

function setCeloFeeHandler() internal {
FeeHandler kontract = new FeeHandler({ test: false });

address precompile = CeloPredeploys.FEE_HANDLER;
string memory cname = CeloPredeploys.getName(precompile);
console.log("Deploying %s implementation at: %s", cname, address(kontract));

vm.resetNonce(address(kontract));
_setupProxy(precompile, address(kontract));
}

function setCeloMentoFeeHandlerSeller() internal {
MentoFeeHandlerSeller kontract = new MentoFeeHandlerSeller({ test: false });

address precompile = CeloPredeploys.MENTO_FEE_HANDLER_SELLER;
string memory cname = CeloPredeploys.getName(precompile);
console.log("Deploying %s implementation at: %s", cname, address(kontract));

vm.resetNonce(address(kontract));
_setupProxy(precompile, address(kontract));
}

function setCeloUniswapFeeHandlerSeller() internal {
UniswapFeeHandlerSeller kontract = new UniswapFeeHandlerSeller({ test: false });

address precompile = CeloPredeploys.UNISWAP_FEE_HANDLER_SELLER;
string memory cname = CeloPredeploys.getName(precompile);
console.log("Deploying %s implementation at: %s", cname, address(kontract));

vm.resetNonce(address(kontract));
_setupProxy(precompile, address(kontract));
}

function setCeloSortedOracles() internal {
SortedOracles kontract = new SortedOracles({ test: false });

address precompile = CeloPredeploys.SORTED_ORACLES;
string memory cname = CeloPredeploys.getName(precompile);
console.log("Deploying %s implementation at: %s", cname, address(kontract));

vm.resetNonce(address(kontract));
_setupProxy(precompile, address(kontract));
}

function setFeeCurrencyDirectory() internal {
FeeCurrencyDirectory feeCurrencyDirectory = new FeeCurrencyDirectory({ test: false });

address precompile = FEE_CURRENCY_DIRECTORY;
string memory cname = CeloPredeploys.getName(CeloPredeploys.FEE_CURRENCY_DIRECTORY);
console.log("Deploying %s implementation at: %s", cname, address(feeCurrencyDirectory));

vm.resetNonce(address(feeCurrencyDirectory));
_setupProxy(precompile, address(feeCurrencyDirectory));

vm.startPrank(devAccounts[0]);
FeeCurrencyDirectory(precompile).initialize();
vm.stopPrank();
}

function setCeloAddressSortedLinkedListWithMedian() internal {
address precompile = CeloPredeploys.ADDRESS_SORTED_LINKED_LIST_WITH_MEDIAN;
string memory cname = CeloPredeploys.getName(precompile);

console.log("Deploying %s (library) at: %s", cname, precompile);

bytes memory runtimeCode = type(AddressSortedLinkedListWithMedian).runtimeCode;
vm.etch(precompile, runtimeCode);
}

function setCeloFeeCurrency() internal {
FeeCurrency kontract = new FeeCurrency({ name_: "Test", symbol_: "TST" });
address precompile = CeloPredeploys.FEE_CURRENCY;
string memory cname = CeloPredeploys.getName(precompile);
console.log("Deploying %s implementation at: %s", cname, address(kontract));
vm.resetNonce(address(kontract));
_setupProxy(precompile, address(kontract));
}

function deploycUSD(
address[] memory initialBalanceAddresses,
uint256[] memory initialBalanceValues,
uint256 celoPrice
)
public
{
StableTokenV2 kontract = new StableTokenV2({ disable: false });
address cusdProxyAddress = CeloPredeploys.cUSD;
string memory cname = CeloPredeploys.getName(cusdProxyAddress);
console.log("Deploying %s implementation at: %s", cname, address(kontract));
vm.resetNonce(address(kontract));

_setupProxy(cusdProxyAddress, address(kontract));

StableTokenV2(cusdProxyAddress).initialize("Celo Dollar", "cUSD", initialBalanceAddresses, initialBalanceValues);

SortedOracles sortedOracles = SortedOracles(CeloPredeploys.SORTED_ORACLES);

console.log("beofre add oracle");

vm.startPrank(sortedOracles.owner());
sortedOracles.addOracle(cusdProxyAddress, deployer);
vm.stopPrank();
vm.startPrank(deployer);

if (celoPrice != 0) {
sortedOracles.report(cusdProxyAddress, celoPrice * 1e24, address(0), address(0)); // TODO use fixidity
}

/*
Arbitrary intrinsic gas number take from existing `FeeCurrencyDirectory.t.sol` tests
Source:
https://github.com/celo-org/celo-monorepo/blob/2cec07d43328cf4216c62491a35eacc4960fffb6/packages/protocol/test-sol/common/FeeCurrencyDirectory.t.sol#L27
*/
uint256 mockIntrinsicGas = 21000;

FeeCurrencyDirectory feeCurrencyDirectory = FeeCurrencyDirectory(FEE_CURRENCY_DIRECTORY);
vm.startPrank(feeCurrencyDirectory.owner());
feeCurrencyDirectory.setCurrencyConfig(cusdProxyAddress, address(sortedOracles), mockIntrinsicGas);
vm.stopPrank();
vm.startPrank(deployer);
}
}
4 changes: 4 additions & 0 deletions packages/contracts-bedrock/scripts/deploy/DeployConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ contract DeployConfig is Script {
bool public useInterop;
bool public useUpgradedFork;

bool public deployCeloContracts;

function read(string memory _path) public {
console.log("DeployConfig: reading file %s", _path);
try vm.readFile(_path) returns (string memory data_) {
Expand Down Expand Up @@ -180,6 +182,8 @@ contract DeployConfig is Script {

useInterop = _readOr(_json, "$.useInterop", false);
useUpgradedFork;

deployCeloContracts = _readOr(_json, "$.deployCeloContracts", false);
}

function fork() public view returns (Fork fork_) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ contract DeployImplementationsInput is BaseDeployIO {
IProxyAdmin internal _superchainProxyAdmin;
address internal _upgradeController;

bool internal _useDevCeloTokenL1;

function set(bytes4 _sel, uint256 _value) public {
require(_value != 0, "DeployImplementationsInput: cannot set zero value");

Expand Down Expand Up @@ -92,6 +94,11 @@ contract DeployImplementationsInput is BaseDeployIO {
else revert("DeployImplementationsInput: unknown selector");
}

function set(bytes4 _sel, bool _value) public {
if (_sel == this.useDevCeloTokenL1.selector) _useDevCeloTokenL1 = _value;
else revert("DeployImplementationsInput: unknown selector");
}

function withdrawalDelaySeconds() public view returns (uint256) {
require(_withdrawalDelaySeconds != 0, "DeployImplementationsInput: not set");
return _withdrawalDelaySeconds;
Expand Down Expand Up @@ -149,6 +156,10 @@ contract DeployImplementationsInput is BaseDeployIO {
require(address(_upgradeController) != address(0), "DeployImplementationsInput: not set");
return _upgradeController;
}

function useDevCeloTokenL1() public view returns (bool) {
return _useDevCeloTokenL1;
}
}

contract DeployImplementationsOutput is BaseDeployIO {
Expand Down Expand Up @@ -581,7 +592,13 @@ contract DeployImplementations is Script {
require(checkAddress == address(0), "OPCM-40");
(blueprints.resolvedDelegateProxy, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode("ResolvedDelegateProxy"), _salt);
require(checkAddress == address(0), "OPCM-50");
(blueprints.celoTokenL1, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode("CeloTokenL1"), _salt);

string memory celoTokenL1Contract = "CeloTokenL1";
if (_dii.useDevCeloTokenL1()) {
celoTokenL1Contract = "DevCeloTokenL1";
}

(blueprints.celoTokenL1, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode(celoTokenL1Contract), _salt);
require(checkAddress == address(0), "CELO_50");
// The max initcode/runtimecode size is 48KB/24KB.
// But for Blueprint, the initcode is stored as runtime code, that's why it's necessary to split into 2 parts.
Expand Down
Loading