Skip to content
Open
Show file tree
Hide file tree
Changes from all 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