Skip to content

Commit

Permalink
Contract fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mdehoog committed Sep 28, 2024
1 parent aebe5b4 commit e362abb
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 71 deletions.
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ libs = ["lib"]

viaIR = true
ffi = true
evm_version = "shanghai"
fs_permissions = [
{ access='read', path='./deploy-config/' },
{ access='read-write', path='./deployments/' }
Expand Down
69 changes: 65 additions & 4 deletions script/DeploySystem.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import { OptimismPortal } from "@eth-optimism-bedrock/src/L1/OptimismPortal.sol"
import { L2OutputOracle } from "@eth-optimism-bedrock/src/L1/L2OutputOracle.sol";
import { Portal } from "src/Portal.sol";
import { OutputOracle } from "src/OutputOracle.sol";
import { OwnerConfig } from "src/OwnerConfig.sol";
import { SystemConfigOwnable } from "src/SystemConfigOwnable.sol";
import { SystemConfigGlobal } from "src/SystemConfigGlobal.sol";
import { DeployChain } from "src/DeployChain.sol";
import { Constants } from "@eth-optimism-bedrock/src/libraries/Constants.sol";
import { ResourceMetering } from "@eth-optimism-bedrock/src/L1/ResourceMetering.sol";

Expand All @@ -26,6 +29,8 @@ contract DeploySystem is Deploy {
console.log("set up superchain!");
setupOpChain2();
console.log("set up op chain!");
setupChainDeploy();
console.log("set chain deploy!");
}

function setupSuperchain2() public {
Expand Down Expand Up @@ -63,16 +68,22 @@ contract DeploySystem is Deploy {
initializeImplementations2();
}

function setupChainDeploy() public {
console.log("Setting up Chain Deploy");

deployDeployChain();
}

function deployProxies2() public {
console.log("Deploying proxies");

deployERC1967Proxy("OptimismPortalProxy");
deployERC1967Proxy("SystemConfigProxy");
deployERC1967Proxy("SystemConfigGlobalProxy");
deployL1StandardBridgeProxy();
deployL1CrossDomainMessengerProxy();
deployERC1967Proxy("OptimismMintableERC20FactoryProxy");
deployERC1967Proxy("L1ERC721BridgeProxy");

deployERC1967Proxy("L2OutputOracleProxy");

transferAddressManagerOwnership(); // to the ProxyAdmin
Expand All @@ -88,6 +99,7 @@ contract DeploySystem is Deploy {
deployL1CrossDomainMessenger();
deployOptimismMintableERC20Factory();
deploySystemConfigOwnable();
deploySystemConfigGlobal();
deployL1StandardBridge();
deployL1ERC721Bridge();
deployPortal();
Expand All @@ -98,6 +110,7 @@ contract DeploySystem is Deploy {
console.log("Initializing implementations");
initializePortal();
initializeSystemConfigOwnable();
initializeSystemConfigGlobal();
initializeL1StandardBridge();
initializeL1ERC721Bridge();
initializeOptimismMintableERC20Factory();
Expand All @@ -106,8 +119,11 @@ contract DeploySystem is Deploy {
}

function deploySystemConfigOwnable() public broadcast returns (address addr_) {
console.log("Deploying OwnerConfig");
OwnerConfig ownerConfig = new OwnerConfig{ salt: _implSalt() }(cfg.finalSystemOwner());

console.log("Deploying SystemConfig implementation");
addr_ = address(new SystemConfigOwnable{ salt: _implSalt() }(cfg.finalSystemOwner()));
addr_ = address(new SystemConfigOwnable{ salt: _implSalt() }(ownerConfig));
save("SystemConfig", addr_);
console.log("SystemConfig deployed at %s", addr_);

Expand All @@ -119,6 +135,13 @@ contract DeploySystem is Deploy {
checkSystemConfig({ _contracts: contracts, _cfg: cfg, _isProxy: false });
}

function deploySystemConfigGlobal() public broadcast returns (address addr_) {
console.log("Deploying SystemConfigGlobal implementation");
addr_ = address(new SystemConfigGlobal{ salt: _implSalt() }());
save("SystemConfigGlobal", addr_);
console.log("SystemConfigGlobal deployed at %s", addr_);
}

function deployPortal() public broadcast returns (address addr_) {
console.log("Deploying OptimismPortal implementation");
addr_ = address(new Portal{ salt: _implSalt() }());
Expand All @@ -134,9 +157,11 @@ contract DeploySystem is Deploy {
}

function deployOutputOracle() public broadcast returns (address addr_) {
SystemConfigGlobal systemConfigGlobal = SystemConfigGlobal(mustGetAddress("SystemConfigGlobal"));

console.log("Deploying L2OutputOracle implementation");
OutputOracle oracle = new OutputOracle{ salt: _implSalt() }(
cfg.l2OutputOracleProposer(),
systemConfigGlobal,
1000 // TODO move to config
);

Expand All @@ -157,6 +182,26 @@ contract DeploySystem is Deploy {
addr_ = address(oracle);
}

function deployDeployChain() public broadcast returns (address addr_) {
console.log("Deploying DeployChain implementation");
DeployChain deployChain = new DeployChain{ salt: _implSalt() }({
_proxyAdmin: mustGetAddress("ProxyAdmin"),
_portal: mustGetAddress("OptimismPortalProxy"),
_systemConfig: mustGetAddress("SystemConfigProxy"),
_l1StandardBridge: mustGetAddress("L1StandardBridgeProxy"),
_l1ERC721Bridge: mustGetAddress("L1ERC721BridgeProxy"),
_optimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"),
_l1CrossDomainMessenger: mustGetAddress("L1CrossDomainMessengerProxy"),
_outputOracle: mustGetAddress("L2OutputOracleProxy"),
_superchainConfig: mustGetAddress("SuperchainConfigProxy")
});

save("DeployChain", address(deployChain));
console.log("DeployChain deployed at %s", address(deployChain));

addr_ = address(deployChain);
}

function initializeSystemConfigOwnable() public broadcast {
console.log("Upgrading and initializing SystemConfig proxy");
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
Expand Down Expand Up @@ -197,6 +242,22 @@ contract DeploySystem is Deploy {
checkSystemConfig({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
}

function initializeSystemConfigGlobal() public broadcast {
console.log("Upgrading and initializing SystemConfigGlobal proxy");
address systemConfigGlobalProxy = mustGetAddress("SystemConfigGlobalProxy");
address systemConfigGlobal = mustGetAddress("SystemConfigGlobal");

_upgradeAndCallViaSafe({
_proxy: payable(systemConfigGlobalProxy),
_implementation: systemConfigGlobal,
_innerCallData: abi.encodeWithSelector(SystemConfigGlobal.initialize.selector, cfg.finalSystemOwner())
});

SystemConfigGlobal config = SystemConfigGlobal(systemConfigGlobalProxy);
string memory version = config.version();
console.log("SystemConfigGlobal version: %s", version);
}

function initializePortal() public broadcast {
console.log("Upgrading and initializing OptimismPortal proxy");
address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
Expand Down Expand Up @@ -226,7 +287,7 @@ contract DeploySystem is Deploy {
}

function initializeOutputOracle() public broadcast {
console.log("Upgrading and initializing L2OutputOracle proxy");
console.log("Upgrading and initializing OutputOracle proxy");
address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");
address l2OutputOracle = mustGetAddress("L2OutputOracle");

Expand Down
69 changes: 58 additions & 11 deletions src/DeployChain.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
import { Portal } from "./Portal.sol";
import { OutputOracle } from "./OutputOracle.sol";
import { SystemConfigOwnable } from "./SystemConfigOwnable.sol";
Expand All @@ -16,6 +15,17 @@ import { OptimismMintableERC20Factory } from "@eth-optimism-bedrock/src/universa
import { ResourceMetering } from "@eth-optimism-bedrock/src/L1/ResourceMetering.sol";

contract DeployChain {
struct PerChainConfig {
uint256 chainID;
bytes32 genesisL1Hash;
uint64 genesisL1Number;
bytes32 genesisL2Hash;
uint64 genesisL2Time;
address depositContractAddress;
address l1SystemConfigAddress;
}

address public immutable proxyAdmin;
address public immutable portal;
address public immutable systemConfig;
address public immutable l1StandardBridge;
Expand All @@ -26,6 +36,7 @@ contract DeployChain {
address public immutable superchainConfig;

constructor(
address _proxyAdmin,
address _portal,
address _systemConfig,
address _l1StandardBridge,
Expand All @@ -35,6 +46,7 @@ contract DeployChain {
address _outputOracle,
address _superchainConfig
) {
proxyAdmin = _proxyAdmin;
portal = _portal;
systemConfig = _systemConfig;
l1StandardBridge = _l1StandardBridge;
Expand All @@ -45,19 +57,54 @@ contract DeployChain {
superchainConfig = _superchainConfig;
}

function deploy(bytes32 salt) public {
address _outputOracle = Clones.cloneDeterministic(outputOracle, salt);
address _systemConfig = Clones.cloneDeterministic(systemConfig, salt);
address _portal = Clones.cloneDeterministic(portal, salt);
address _l1CrossDomainMessenger = Clones.cloneDeterministic(l1CrossDomainMessenger, salt);
address _l1StandardBridge = Clones.cloneDeterministic(l1StandardBridge, salt);
address _l1ERC721Bridge = Clones.cloneDeterministic(l1ERC721Bridge, salt);
address _optimismMintableERC20Factory = Clones.cloneDeterministic(optimismMintableERC20Factory, salt);
function setupProxy(address proxy, bytes32 salt) internal returns (address instance) {
address _proxyAdmin = proxyAdmin;
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x60678060095f395ff363204e1c7a60e01b5f5273000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, proxy))
mstore(add(ptr, 0x28), 0x6004525f5f60245f730000000000000000000000000000000000000000000000)
mstore(add(ptr, 0x31), shl(0x60, _proxyAdmin))
mstore(add(ptr, 0x45), 0x5afa3d5f5f3e3d60201416604d573d5ffd5b5f5f365f5f51365f5f375af43d5f)
mstore(add(ptr, 0x65), 0x5f3e5f3d91606557fd5bf3000000000000000000000000000000000000000000)
instance := create2(0, ptr, 0x70, salt)
}
require(instance != address(0), "Proxy: create2 failed");
}

function deploy(bytes32 salt, uint256 chainID, bytes32 genesisHash) external {
address _outputOracle = setupProxy(outputOracle, salt);
address _systemConfig = setupProxy(systemConfig, salt);
address _portal = setupProxy(portal, salt);
address _l1CrossDomainMessenger = setupProxy(l1CrossDomainMessenger, salt);
address _l1StandardBridge = setupProxy(l1StandardBridge, salt);
address _l1ERC721Bridge = setupProxy(l1ERC721Bridge, salt);
address _optimismMintableERC20Factory = setupProxy(optimismMintableERC20Factory, salt);

PerChainConfig memory config = PerChainConfig({
chainID: chainID,
genesisL1Hash: blockhash(block.number-1),
genesisL1Number: uint64(block.number-1),
genesisL2Hash: genesisHash,
genesisL2Time: uint64(block.timestamp-2),
depositContractAddress: _portal,
l1SystemConfigAddress: _systemConfig
});
bytes32 configHash = keccak256(abi.encodePacked(
uint64(0), // version
config.chainID,
config.genesisL1Hash,
config.genesisL1Number,
config.genesisL2Hash,
config.genesisL2Time,
config.depositContractAddress,
config.l1SystemConfigAddress
));

bytes32 configHash = 0; // TODO
OutputOracle(_outputOracle).initialize(configHash);

SystemConfig _configTemplate = SystemConfig(systemConfig);
SystemConfigOwnable _configTemplate = SystemConfigOwnable(systemConfig);
SystemConfigOwnable(_systemConfig).initialize({
_basefeeScalar: _configTemplate.basefeeScalar(),
_blobbasefeeScalar: _configTemplate.blobbasefeeScalar(),
Expand Down
33 changes: 15 additions & 18 deletions src/OutputOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ISemver } from "@eth-optimism-bedrock/src/universal/ISemver.sol";
import { Types } from "@eth-optimism-bedrock/src/libraries/Types.sol";
import { Constants } from "@eth-optimism-bedrock/src/libraries/Constants.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { SystemConfigGlobal } from "./SystemConfigGlobal.sol";

/// @custom:proxied
/// @title OutputOracle
Expand All @@ -20,24 +21,20 @@ import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
/// - Additional signature validation for proposeL2Output
/// - Allow outputs to be proposed at any time
contract OutputOracle is Initializable, ISemver {
/// @notice An array of L2 output proposals.
Types.OutputProposal[] internal l2Outputs;

/// @notice The address of the proposer. Can be updated via upgrade.
/// @custom:network-specific
address public immutable proposer;
/// @notice Global system config.
SystemConfigGlobal public immutable systemConfigGlobal;

/// @notice Maximum number of outputs to store in l2Outputs.
uint256 public immutable maxOutputCount;

/// @notice An array of L2 output proposals.
Types.OutputProposal[] internal l2Outputs;

/// @notice Pointer inside l2Outputs to the latest submitted output.
uint256 public latestOutputIndex;

/// @notice Hash of the serialized chain configuration.
bytes32 private configHash;

/// @notice Mapping of valid signers attested from AWS Nitro.
mapping(address => bool) public validSigners;
bytes32 public configHash;

/// @notice Emitted when an output is proposed.
/// @param outputRoot The output root.
Expand All @@ -52,15 +49,15 @@ contract OutputOracle is Initializable, ISemver {
/// @custom:semver 1.0.0
string public constant version = "1.0.0";

/// @notice Constructs the L3OutputOracle contract. Initializes variables to the same values as
/// @notice Constructs the OutputOracle contract. Initializes variables to the same values as
/// in the getting-started config.
/// @param _proposer The address of the proposer.
/// @param _systemConfigGlobal The global system config contract.
/// @param _maxOutputCount The maximum number of outputs stored by this contract.
constructor(
address _proposer,
SystemConfigGlobal _systemConfigGlobal,
uint256 _maxOutputCount
) {
proposer = _proposer;
systemConfigGlobal = _systemConfigGlobal;
maxOutputCount = _maxOutputCount;
initialize(0);
}
Expand All @@ -71,8 +68,8 @@ contract OutputOracle is Initializable, ISemver {
latestOutputIndex = maxOutputCount-1;
}

function registerSigner(bytes calldata attestation) external {
// TODO validate AWS attestation, check PCR0, then add public key to mapping of valid signers
function proposer() public view returns (address) {
return systemConfigGlobal.proposer();
}

/// @notice Accepts an outputRoot of the corresponding L2 block.
Expand All @@ -87,7 +84,7 @@ contract OutputOracle is Initializable, ISemver {
external
payable
{
require(msg.sender == proposer, "OutputOracle: only the proposer address can propose new outputs");
require(msg.sender == proposer(), "OutputOracle: only the proposer address can propose new outputs");

require(
_l2BlockNumber > latestBlockNumber(),
Expand All @@ -101,7 +98,7 @@ contract OutputOracle is Initializable, ISemver {
keccak256(abi.encodePacked(configHash, blockhash(_l1BlockNumber), previousOutputRoot, _outputRoot)),
_signature
);
require(validSigners[signer], "OutputOracle: invalid signature");
require(systemConfigGlobal.validSigners(signer), "OutputOracle: invalid signature");

latestOutputIndex = nextOutputIndex();
emit OutputProposed(_outputRoot, latestOutputIndex, _l2BlockNumber, block.timestamp);
Expand Down
28 changes: 28 additions & 0 deletions src/OwnableConfig.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./OwnerConfig.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

abstract contract OwnableConfig is Initializable, ContextUpgradeable {
OwnerConfig public immutable ownerConfig;

constructor(OwnerConfig _ownerConfig) {
ownerConfig = _ownerConfig;
}

modifier onlyOwner() {
_checkOwner();
_;
}

function owner() public view virtual returns (address) {
return ownerConfig.owner();
}

function _checkOwner() internal view virtual {
ownerConfig.checkOwner(_msgSender());
}
}
Loading

0 comments on commit e362abb

Please sign in to comment.