Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
martinvol committed Jan 28, 2025
1 parent 5115ad8 commit 422d097
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 25 deletions.
1 change: 1 addition & 0 deletions packages/contracts-bedrock/lib/solady-v0.0.245
Submodule solady-v0.0.245 added at e0ef35
74 changes: 49 additions & 25 deletions packages/contracts-bedrock/scripts/L2Genesis.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ interface IInitializable {
function initialize(address _addr) external;
}



struct L1Dependencies {
address payable l1CrossDomainMessengerProxy;
address payable l1StandardBridgeProxy;
Expand All @@ -71,9 +73,10 @@ contract L2Genesis is Deployer {
using ForkUtils for Fork;
using OutputModeUtils for OutputMode;

address constant defaultOwner = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; // TODO this is DEV_ACCOUNT_FUND_AMT
uint256 public constant PRECOMPILE_COUNT = 256;

uint80 internal constant DEV_ACCOUNT_FUND_AMT = 10_000 ether;
uint80 internal constant DEV_ACCOUNT_FUND_AMT = 60_000 ether;

/// @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,
Expand Down Expand Up @@ -675,6 +678,8 @@ contract L2Genesis is Deployer {
console.log("Funding dev account %s with %s ETH", devAccounts[i], DEV_ACCOUNT_FUND_AMT / 1e18);
vm.deal(devAccounts[i], DEV_ACCOUNT_FUND_AMT);
}
// fund an address that'd then be used to fund the celoUnreleasedTreasury
vm.deal(devAccounts[1], 400_000_000 ether);
}

///@notice Sets all proxies and implementations for Celo contracts
Expand All @@ -690,6 +695,7 @@ contract L2Genesis is Deployer {
setFeeCurrencyDirectory();
}


/// @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");
Expand All @@ -703,58 +709,76 @@ contract L2Genesis is Deployer {
}

function setCeloRegistry() internal {
CeloRegistry kontract = new CeloRegistry({ test: false });
// deployCodeTo("CeloRegistry.sol", abi.encode(false), REGISTRY_ADDRESS);

// address REGISTRY_ADDRESS = address(0x000000000000000000000000000000000000CE11);
// bytes memory code = vm.getDeployedCode("CeloRegistry.sol:CeloRegistry");
// vm.etch(REGISTRY_ADDRESS, code);

CeloRegistry contract_ = 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));
console.log("Deploying %s implementation at: %s", cname, address(contract_));

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

CeloRegistry registry = CeloRegistry(precompile);
address celoOwner = registry.owner();
vm.startPrank(address(celoOwner));
registry.transferOwnership(defaultOwner);
vm.stopPrank();
vm.deal(defaultOwner, 600000e18);

console.log("CeloRegistry owner: %s", celoOwner);
// revert("vert on puporse");

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

function setCeloGoldToken() internal {
GoldToken kontract = new GoldToken({ test: false });
GoldToken contract_ = 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));
console.log("Deploying %s implementation at: %s", cname, address(contract_));

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

function setCeloFeeHandler() internal {
FeeHandler kontract = new FeeHandler({ test: false });
FeeHandler contract_ = 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));
console.log("Deploying %s implementation at: %s", cname, address(contract_));

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

function setCeloMentoFeeHandlerSeller() internal {
MentoFeeHandlerSeller kontract = new MentoFeeHandlerSeller({ test: false });
MentoFeeHandlerSeller contract_ = 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));
console.log("Deploying %s implementation at: %s", cname, address(contract_));

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

function setCeloUniswapFeeHandlerSeller() internal {
UniswapFeeHandlerSeller kontract = new UniswapFeeHandlerSeller({ test: false });
UniswapFeeHandlerSeller contract_ = 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));
console.log("Deploying %s implementation at: %s", cname, address(contract_));

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

function setFeeCurrencyDirectory() internal {
Expand All @@ -773,11 +797,11 @@ contract L2Genesis is Deployer {
}

function setCeloFeeCurrency() internal {
FeeCurrency kontract = new FeeCurrency({ name_: "Test", symbol_: "TST" });
FeeCurrency contract_ = 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));
console.log("Deploying %s implementation at: %s", cname, address(contract_));
vm.resetNonce(address(contract_));
_setupProxy(precompile, address(contract_));
}
}
161 changes: 161 additions & 0 deletions packages/contracts-bedrock/src/celo/CeloProxy.s_ol
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
pragma solidity ^0.5.13;
/* solhint-disable no-inline-assembly, no-complex-fallback, avoid-low-level-calls */

import "openzeppelin-solidity/contracts/utils/Address.sol";

/**
* @title A Proxy utilizing the Unstructured Storage pattern.
*/
contract CeloProxy {
// Used to store the address of the owner.
bytes32 private constant OWNER_POSITION = bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1);
// Used to store the address of the implementation contract.
bytes32 private constant IMPLEMENTATION_POSITION =
bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);

event OwnerSet(address indexed owner);
event ImplementationSet(address indexed implementation);

/**
* @notice Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == _getOwner(), "sender was not owner");
_;
}

constructor() public {
_setOwner(msg.sender);
}

/**
* @notice Delegates calls to the implementation contract.
*/
function() external payable {
bytes32 implementationPosition = IMPLEMENTATION_POSITION;

address implementationAddress;

// Load the address of the implementation contract from an explicit storage slot.
assembly {
implementationAddress := sload(implementationPosition)
}

// Avoid checking if address is a contract or executing delegated call when
// implementation address is 0x0
require(implementationAddress != address(0), "No Implementation set");
require(Address.isContract(implementationAddress), "Invalid contract address");

assembly {
// Extract the position of the transaction data (i.e. function ID and arguments).
let newCallDataPosition := mload(0x40)
mstore(0x40, add(newCallDataPosition, calldatasize))
calldatacopy(newCallDataPosition, 0, calldatasize)

// Call the smart contract at `implementationAddress` in the context of the proxy contract,
// with the same msg.sender and value.
let delegatecallSuccess := delegatecall(
gas,
implementationAddress,
newCallDataPosition,
calldatasize,
0,
0
)

// Copy the return value of the call so it can be returned.
let returnDataSize := returndatasize
let returnDataPosition := mload(0x40)
mstore(0x40, add(returnDataPosition, returnDataSize))
returndatacopy(returnDataPosition, 0, returnDataSize)

// Revert or return depending on whether or not the call was successful.
switch delegatecallSuccess
case 0 {
revert(returnDataPosition, returnDataSize)
}
default {
return(returnDataPosition, returnDataSize)
}
}
}

/**
* @notice Transfers ownership of Proxy to a new owner.
* @param newOwner Address of the new owner account.
*/
function _transferOwnership(address newOwner) external onlyOwner {
_setOwner(newOwner);
}

/**
* @notice Sets the address of the implementation contract and calls into it.
* @param implementation Address of the new target contract.
* @param callbackData The abi-encoded function call to perform in the implementation
* contract.
* @dev Throws if the initialization callback fails.
* @dev If the target contract does not need initialization, use
* setImplementation instead.
*/
function _setAndInitializeImplementation(
address implementation,
bytes calldata callbackData
) external payable onlyOwner {
_setImplementation(implementation);
bool success;
bytes memory returnValue;
(success, returnValue) = implementation.delegatecall(callbackData);
require(success, "initialization callback failed");
}

/**
* @notice Returns the implementation address.
*/
function _getImplementation() external view returns (address implementation) {
bytes32 implementationPosition = IMPLEMENTATION_POSITION;
// Load the address of the implementation contract from an explicit storage slot.
assembly {
implementation := sload(implementationPosition)
}
}

/**
* @notice Sets the address of the implementation contract.
* @param implementation Address of the new target contract.
* @dev If the target contract needs to be initialized, call
* setAndInitializeImplementation instead.
*/
function _setImplementation(address implementation) public onlyOwner {
bytes32 implementationPosition = IMPLEMENTATION_POSITION;

require(Address.isContract(implementation), "Invalid contract address");

// Store the address of the implementation contract in an explicit storage slot.
assembly {
sstore(implementationPosition, implementation)
}

emit ImplementationSet(implementation);
}

/**
* @notice Returns the Proxy owner's address.
*/
function _getOwner() public view returns (address owner) {
bytes32 position = OWNER_POSITION;
// Load the address of the contract owner from an explicit storage slot.
assembly {
owner := sload(position)
}
}

function _setOwner(address newOwner) internal {
require(newOwner != address(0), "owner cannot be 0");
bytes32 position = OWNER_POSITION;
// Store the address of the contract owner in an explicit storage slot.
assembly {
sstore(position, newOwner)
}
emit OwnerSet(newOwner);
}
}

0 comments on commit 422d097

Please sign in to comment.