Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ERC20 Factory Storage #6839

Merged
merged 8 commits into from
Aug 17, 2023
Merged
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
194 changes: 190 additions & 4 deletions op-bindings/bindings/optimismmintableerc20factory.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions op-bindings/bindings/optimismmintableerc20factory_more.go

Large diffs are not rendered by default.

27 changes: 24 additions & 3 deletions op-chain-ops/cmd/check-l2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,15 +543,36 @@ func checkOptimismMintableERC20Factory(addr common.Address, client *ethclient.Cl
return err
}

bridge, err := contract.BRIDGE(&bind.CallOpts{})
bridgeLegacy, err := contract.BRIDGE(&bind.CallOpts{})
if err != nil {
return err
}
log.Info("OptimismMintableERC20Factory", "BRIDGE", bridge.Hex())
if bridge == (common.Address{}) {
log.Info("OptimismMintableERC20Factory", "BRIDGE", bridgeLegacy.Hex())
if bridgeLegacy == (common.Address{}) {
return errors.New("OptimismMintableERC20Factory.BRIDGE is zero address")
}

bridge, err := contract.Bridge(&bind.CallOpts{})
if err != nil {
return err
}
if bridge == (common.Address{}) {
return errors.New("OptimismMintableERC20Factory.bridge is zero address")
}
log.Info("OptimismMintableERC20Factory", "bridge", bridge.Hex())

initialized, err := getInitialized("OptimismMintableERC20Factory", addr, client)
if err != nil {
return err
}
log.Info("OptimismMintableERC20Factory", "_initialized", initialized)

initializing, err := getInitializing("OptimismMintableERC20Factory", addr, client)
if err != nil {
return err
}
log.Info("OptimismMintableERC20Factory", "_initializing", initializing)

version, err := contract.Version(&bind.CallOpts{})
if err != nil {
return err
Expand Down
5 changes: 5 additions & 0 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,11 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
"_initialized": 2,
"_initializing": false,
}
storage["OptimismMintableERC20Factory"] = state.StorageValues{
"bridge": predeploys.L2StandardBridgeAddr,
"_initialized": 2,
"_initializing": false,
}
return storage, nil
}

Expand Down
2 changes: 1 addition & 1 deletion op-chain-ops/immutables/immutables.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep
}
_, tx, _, err = bindings.DeployL1FeeVault(opts, backend, recipient, minimumWithdrawalAmount, withdrawalNetwork)
case "OptimismMintableERC20Factory":
_, tx, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend, predeploys.L2StandardBridgeAddr)
_, tx, _, err = bindings.DeployOptimismMintableERC20Factory(opts, backend)
case "DeployerWhitelist":
_, tx, _, err = bindings.DeployDeployerWhitelist(opts, backend)
case "LegacyMessagePasser":
Expand Down
8 changes: 4 additions & 4 deletions packages/contracts-bedrock/.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -423,10 +423,10 @@ OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11121)
OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140547)
OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9005)
OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163441)
OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 7646)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9401)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516769032)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1293594)
OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 9760)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9471)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516769105)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1295838)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 11178)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16111)
OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26781)
Expand Down
7 changes: 5 additions & 2 deletions packages/contracts-bedrock/.storage-layout
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,11 @@
➡ src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory
=======================

| Name | Type | Slot | Offset | Bytes | Contract |
|------|------|------|--------|-------|----------|
| Name | Type | Slot | Offset | Bytes | Contract |
|---------------|---------|------|--------|-------|-----------------------------------------------------------------------------|
| _initialized | uint8 | 0 | 0 | 1 | src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory |
| _initializing | bool | 0 | 1 | 1 | src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory |
| bridge | address | 0 | 2 | 20 | src/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory |

=======================
➡ src/dispute/DisputeGameFactory.sol:DisputeGameFactory
Expand Down
12 changes: 7 additions & 5 deletions packages/contracts-bedrock/scripts/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,10 @@ contract Deploy is Deployer {

/// @notice Deploy the OptimismMintableERC20Factory
function deployOptimismMintableERC20Factory() public broadcast returns (address addr_) {
address l1StandardBridgeProxy = mustGetAddress("L1StandardBridgeProxy");
OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(l1StandardBridgeProxy);
OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory();

require(factory.BRIDGE() == l1StandardBridgeProxy);
require(factory.BRIDGE() == address(0));
require(factory.bridge() == address(0));

save("OptimismMintableERC20Factory", address(factory));
console.log("OptimismMintableERC20Factory deployed at %s", address(factory));
Expand Down Expand Up @@ -613,16 +613,18 @@ contract Deploy is Deployer {
address optimismMintableERC20Factory = mustGetAddress("OptimismMintableERC20Factory");
address l1StandardBridgeProxy = mustGetAddress("L1StandardBridgeProxy");

proxyAdmin.upgrade({
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismMintableERC20FactoryProxy),
_implementation: optimismMintableERC20Factory
_implementation: optimismMintableERC20Factory,
_data: abi.encodeCall(OptimismMintableERC20Factory.initialize, (l1StandardBridgeProxy))
});

OptimismMintableERC20Factory factory = OptimismMintableERC20Factory(optimismMintableERC20FactoryProxy);
string memory version = factory.version();
console.log("OptimismMintableERC20Factory version: %s", version);

require(factory.BRIDGE() == l1StandardBridgeProxy);
require(factory.bridge() == l1StandardBridgeProxy);
}

/// @notice initializeL1CrossDomainMessenger
Expand Down
2 changes: 1 addition & 1 deletion packages/contracts-bedrock/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"src/periphery/op-nft/OptimistAllowlist.sol": "0x53e9a9dfecbae036fd468e8f34c80c7d9c35bd8908c8a6483db44dbc5128ad69",
"src/periphery/op-nft/OptimistInviter.sol": "0xfdd5b9d45205ef9372ba37f7a6394724695e676d27a47cb154ee6e4148490013",
"src/universal/OptimismMintableERC20.sol": "0xa0b4f168802d0f9eca9ddc54347ca66c34ad7aa0fd84b01e0d7e99a9f86f46d6",
"src/universal/OptimismMintableERC20Factory.sol": "0x8afb6b634f40e8ac8c60ec7e2ca3bcd610b020d09b3cae70a3d4995722cab3ce",
"src/universal/OptimismMintableERC20Factory.sol": "0xf4beb7fed4defc3e70b2298831bf0024cceaa8f1cf55fd98c00f5998b8ab5589",
"src/universal/OptimismMintableERC721.sol": "0x49dc863caf3e002bf0c90b3af3873990fb282771f4c63735fd61a885b7873983",
"src/universal/OptimismMintableERC721Factory.sol": "0x502438b009bfaf0ab187914662468261f10446fd85d44a79b29cdaef7b4982ba"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity 0.8.15;

import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { Semver } from "./Semver.sol";

/// @custom:proxied
Expand All @@ -11,9 +12,10 @@ import { Semver } from "./Semver.sol";
/// contracts on the network it's deployed to. Simplifies the deployment process for users
/// who may be less familiar with deploying smart contracts. Designed to be backwards
/// compatible with the older StandardL2ERC20Factory contract.
contract OptimismMintableERC20Factory is Semver {
contract OptimismMintableERC20Factory is Semver, Initializable {
/// @notice Address of the StandardBridge on this chain.
address public immutable BRIDGE;
/// @custom:network-specific
address public bridge;

/// @custom:legacy
/// @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer
Expand All @@ -28,13 +30,25 @@ contract OptimismMintableERC20Factory is Semver {
/// @param deployer Address of the account that deployed the token.
event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer);

/// @custom:semver 1.2.0
/// @custom:semver 1.3.0
/// @notice The semver MUST be bumped any time that there is a change in
/// the OptimismMintableERC20 token contract since this contract
/// is responsible for deploying OptimismMintableERC20 contracts.
constructor() Semver(1, 3, 0) {
initialize({ _bridge: address(0) });
}

/// @notice Initializer.
/// @param _bridge Address of the StandardBridge on this chain.
constructor(address _bridge) Semver(1, 2, 0) {
BRIDGE = _bridge;
function initialize(address _bridge) public reinitializer(2) {
bridge = _bridge;
}

/// @notice Returns the address of the StandardBridge on this chain.
/// This is a legacy getter, use `bridge` instead.
/// @custom:legacy
function BRIDGE() external view returns (address) {
return bridge;
}

/// @custom:legacy
Expand Down Expand Up @@ -71,7 +85,7 @@ contract OptimismMintableERC20Factory is Semver {
require(_remoteToken != address(0), "OptimismMintableERC20Factory: must provide remote token address");

bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol));
address localToken = address(new OptimismMintableERC20{salt: salt}(BRIDGE, _remoteToken, _name, _symbol));
address localToken = address(new OptimismMintableERC20{salt: salt}(bridge, _remoteToken, _name, _symbol));

// Emit the old event too for legacy support.
emit StandardL2TokenCreated(_remoteToken, localToken);
Expand Down
18 changes: 13 additions & 5 deletions packages/contracts-bedrock/test/CommonTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -377,17 +377,17 @@ contract Bridge_Initializer is Messenger_Initializer {
vm.label(address(L1Bridge_Impl), "L1StandardBridge_Impl");

// Deploy the L2StandardBridge, move it to the correct predeploy
// address and then initialize it
// address and then initialize it. It is safe to call initialize directly
// on the proxy because the bytecode was set in state with `etch`.
vm.etch(Predeploys.L2_STANDARD_BRIDGE, address(new L2StandardBridge(StandardBridge(payable(proxy)))).code);
L2Bridge = L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE));
L2Bridge.initialize();

// Set up the L2 mintable token factory
OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory(
Predeploys.L2_STANDARD_BRIDGE
);
OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory();
vm.etch(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, address(factory).code);
L2TokenFactory = OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY);
L2TokenFactory.initialize(Predeploys.L2_STANDARD_BRIDGE);

vm.etch(Predeploys.LEGACY_ERC20_ETH, address(new LegacyERC20ETH()).code);

Expand Down Expand Up @@ -419,7 +419,15 @@ contract Bridge_Initializer is Messenger_Initializer {
);

NativeL2Token = new ERC20("Native L2 Token", "L2T");
L1TokenFactory = new OptimismMintableERC20Factory(address(L1Bridge));
Proxy factoryProxy = new Proxy(multisig);
OptimismMintableERC20Factory L1TokenFactoryImpl = new OptimismMintableERC20Factory();

vm.prank(multisig);
factoryProxy.upgradeToAndCall(
address(L1TokenFactoryImpl), abi.encodeCall(OptimismMintableERC20Factory.initialize, address(L1Bridge))
);

L1TokenFactory = OptimismMintableERC20Factory(address(factoryProxy));

RemoteL1Token = OptimismMintableERC20(
L1TokenFactory.createStandardL2Token(
Expand Down