Commit c9395875 authored by refcell.eth's avatar refcell.eth Committed by GitHub

fix(ctb): Update universal contracts with Triple Slash Natspec Styling (#6130)

parent 19468e49
This diff is collapsed.
...@@ -271,13 +271,12 @@ OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14322) ...@@ -271,13 +271,12 @@ OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14322)
OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11165) OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11165)
OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63544) OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63544)
OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7667) OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7667)
OptimismMintableERC20_Test:test_semver_succeeds() (gas: 8812)
OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8351) OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8351)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2321820) OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2321820)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9418) OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9418)
OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136966) OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136966)
OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118832) OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118832)
OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 28981) OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 24162)
OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11121) OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11121)
OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140547) OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140547)
OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9005) OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9005)
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
// Testing utilities
import { Messenger_Initializer, Reverter, CallerCaller, CommonTest } from "./CommonTest.t.sol"; import { Messenger_Initializer, Reverter, CallerCaller, CommonTest } from "./CommonTest.t.sol";
import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol"; import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol";
...@@ -12,23 +13,21 @@ import { Encoding } from "../libraries/Encoding.sol"; ...@@ -12,23 +13,21 @@ import { Encoding } from "../libraries/Encoding.sol";
// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2 // CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2
// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract. // CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.
contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer { contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
// Ensure that baseGas passes for the max value of _minGasLimit, /// @dev Ensure that baseGas passes for the max value of _minGasLimit,
// this is about 4 Billion. /// this is about 4 Billion.
function test_baseGas_succeeds() external view { function test_baseGas_succeeds() external view {
L1Messenger.baseGas(hex"ff", type(uint32).max); L1Messenger.baseGas(hex"ff", type(uint32).max);
} }
// Fuzz for other values which might cause a revert in baseGas. /// @dev Fuzz for other values which might cause a revert in baseGas.
function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view { function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {
L1Messenger.baseGas(hex"ff", _minGasLimit); L1Messenger.baseGas(hex"ff", _minGasLimit);
} }
/** /// @notice The baseGas function should always return a value greater than
* @notice The baseGas function should always return a value greater than /// or equal to the minimum gas limit value on the OptimismPortal.
* or equal to the minimum gas limit value on the OptimismPortal. /// This guarantees that the messengers will always pass sufficient
* This guarantees that the messengers will always pass sufficient /// gas to the OptimismPortal.
* gas to the OptimismPortal.
*/
function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit) function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit)
external external
{ {
...@@ -39,11 +38,9 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer { ...@@ -39,11 +38,9 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
} }
} }
/** /// @title ExternalRelay
* @title ExternalRelay /// @notice A mock external contract called via the SafeCall inside
* @notice A mock external contract called via the SafeCall inside /// the CrossDomainMessenger's `relayMessage` function.
* the CrossDomainMessenger's `relayMessage` function.
*/
contract ExternalRelay is CommonTest { contract ExternalRelay is CommonTest {
address internal op; address internal op;
address internal fuzzedSender; address internal fuzzedSender;
...@@ -56,9 +53,7 @@ contract ExternalRelay is CommonTest { ...@@ -56,9 +53,7 @@ contract ExternalRelay is CommonTest {
op = _op; op = _op;
} }
/** /// @notice Internal helper function to relay a message and perform assertions.
* @notice Internal helper function to relay a message and perform assertions.
*/
function _internalRelay(address _innerSender) internal { function _internalRelay(address _innerSender) internal {
address initialSender = L1Messenger.xDomainMessageSender(); address initialSender = L1Messenger.xDomainMessageSender();
...@@ -91,9 +86,7 @@ contract ExternalRelay is CommonTest { ...@@ -91,9 +86,7 @@ contract ExternalRelay is CommonTest {
assertEq(initialSender, L1Messenger.xDomainMessageSender()); assertEq(initialSender, L1Messenger.xDomainMessageSender());
} }
/** /// @notice externalCallWithMinGas is called by the CrossDomainMessenger.
* @notice externalCallWithMinGas is called by the CrossDomainMessenger.
*/
function externalCallWithMinGas() external payable { function externalCallWithMinGas() external payable {
for (uint256 i = 0; i < 10; i++) { for (uint256 i = 0; i < 10; i++) {
address _innerSender; address _innerSender;
...@@ -104,25 +97,19 @@ contract ExternalRelay is CommonTest { ...@@ -104,25 +97,19 @@ contract ExternalRelay is CommonTest {
} }
} }
/** /// @notice Helper function to get the callData for an `externalCallWithMinGas
* @notice Helper function to get the callData for an `externalCallWithMinGas
*/
function getCallData() public pure returns (bytes memory) { function getCallData() public pure returns (bytes memory) {
return abi.encodeWithSelector(ExternalRelay.externalCallWithMinGas.selector); return abi.encodeWithSelector(ExternalRelay.externalCallWithMinGas.selector);
} }
/** /// @notice Helper function to set the fuzzed sender
* @notice Helper function to set the fuzzed sender
*/
function setFuzzedSender(address _fuzzedSender) public { function setFuzzedSender(address _fuzzedSender) public {
fuzzedSender = _fuzzedSender; fuzzedSender = _fuzzedSender;
} }
} }
/** /// @title CrossDomainMessenger_RelayMessage_Test
* @title CrossDomainMessenger_RelayMessage_Test /// @notice Fuzz tests re-entrancy into the CrossDomainMessenger relayMessage function.
* @notice Fuzz tests re-entrancy into the CrossDomainMessenger relayMessage function.
*/
contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer { contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
// Storage slot of the l2Sender // Storage slot of the l2Sender
uint256 constant senderSlotIndex = 50; uint256 constant senderSlotIndex = 50;
...@@ -134,15 +121,13 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer { ...@@ -134,15 +121,13 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
er = new ExternalRelay(L1Messenger, address(op)); er = new ExternalRelay(L1Messenger, address(op));
} }
/** /// @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via
* @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via /// the relayMessage function. The relayMessage function will then use SafeCall's
* the relayMessage function. The relayMessage function will then use SafeCall's /// callWithMinGas to call the target with call data packed in the callMessage.
* callWithMinGas to call the target with call data packed in the callMessage. /// For this test, the callWithMinGas will call the mock ExternalRelay test contract
* For this test, the callWithMinGas will call the mock ExternalRelay test contract /// defined above, executing the externalCallWithMinGas function which will try to
* defined above, executing the externalCallWithMinGas function which will try to /// re-enter the CrossDomainMessenger's relayMessage function, resulting in that message
* re-enter the CrossDomainMessenger's relayMessage function, resulting in that message /// being recorded as failed.
* being recorded as failed.
*/
function testFuzz_relayMessageReenter_succeeds(address _sender, uint256 _gasLimit) external { function testFuzz_relayMessageReenter_succeeds(address _sender, uint256 _gasLimit) external {
vm.assume(_sender != Predeploys.L2_CROSS_DOMAIN_MESSENGER); vm.assume(_sender != Predeploys.L2_CROSS_DOMAIN_MESSENGER);
address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER;
......
...@@ -12,10 +12,6 @@ contract OptimismMintableERC20_Test is Bridge_Initializer { ...@@ -12,10 +12,6 @@ contract OptimismMintableERC20_Test is Bridge_Initializer {
event Mint(address indexed account, uint256 amount); event Mint(address indexed account, uint256 amount);
event Burn(address indexed account, uint256 amount); event Burn(address indexed account, uint256 amount);
function test_semver_succeeds() external {
assertEq(L2Token.version(), "1.0.0");
}
function test_remoteToken_succeeds() external { function test_remoteToken_succeeds() external {
assertEq(L2Token.remoteToken(), address(L1Token)); assertEq(L2Token.remoteToken(), address(L1Token));
} }
......
...@@ -50,12 +50,9 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer { ...@@ -50,12 +50,9 @@ contract OptimismMintableERC721_Test is ERC721Bridge_Initializer {
assertEq(L2Token.REMOTE_TOKEN(), address(L1Token)); assertEq(L2Token.REMOTE_TOKEN(), address(L1Token));
assertEq(L2Token.BRIDGE(), address(L2Bridge)); assertEq(L2Token.BRIDGE(), address(L2Bridge));
assertEq(L2Token.REMOTE_CHAIN_ID(), 1); assertEq(L2Token.REMOTE_CHAIN_ID(), 1);
assertEq(L2Token.version(), "1.1.0");
} }
/** /// @notice Ensure that the contract supports the expected interfaces.
* @notice Ensure that the contract supports the expected interfaces.
*/
function test_supportsInterfaces_succeeds() external { function test_supportsInterfaces_succeeds() external {
// Checks if the contract supports the IOptimismMintableERC721 interface. // Checks if the contract supports the IOptimismMintableERC721 interface.
assertTrue(L2Token.supportsInterface(type(IOptimismMintableERC721).interfaceId)); assertTrue(L2Token.supportsInterface(type(IOptimismMintableERC721).interfaceId));
......
...@@ -5,36 +5,26 @@ import { CommonTest } from "./CommonTest.t.sol"; ...@@ -5,36 +5,26 @@ import { CommonTest } from "./CommonTest.t.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "../universal/Semver.sol";
import { Proxy } from "../universal/Proxy.sol"; import { Proxy } from "../universal/Proxy.sol";
/** /// @notice Test the Semver contract that is used for semantic versioning
* @notice Test the Semver contract that is used for semantic versioning /// of various contracts.
* of various contracts.
*/
contract Semver_Test is CommonTest { contract Semver_Test is CommonTest {
/** /// @notice Global semver contract deployed in setUp. This is used in
* @notice Global semver contract deployed in setUp. This is used in /// the test cases.
* the test cases.
*/
Semver semver; Semver semver;
/** /// @notice Deploy a Semver contract
* @notice Deploy a Semver contract
*/
function setUp() public virtual override { function setUp() public virtual override {
semver = new Semver(7, 8, 0); semver = new Semver(7, 8, 0);
} }
/** /// @notice Test the version getter
* @notice Test the version getter
*/
function test_version_succeeds() external { function test_version_succeeds() external {
assertEq(semver.version(), "7.8.0"); assertEq(semver.version(), "7.8.0");
} }
/** /// @notice Since the versions are all immutable, they should
* @notice Since the versions are all immutable, they should /// be able to be accessed from behind a proxy without needing
* be able to be accessed from behind a proxy without needing /// to initialize the contract.
* to initialize the contract.
*/
function test_behindProxy_succeeds() external { function test_behindProxy_succeeds() external {
Proxy proxy = new Proxy(alice); Proxy proxy = new Proxy(alice);
vm.prank(alice); vm.prank(alice);
......
...@@ -9,11 +9,9 @@ import { ...@@ -9,11 +9,9 @@ import {
} from "../universal/OptimismMintableERC20.sol"; } from "../universal/OptimismMintableERC20.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/** /// @title StandardBridgeTester
* @title StandardBridgeTester /// @notice Simple wrapper around the StandardBridge contract that exposes
* @notice Simple wrapper around the StandardBridge contract that exposes /// internal functions so they can be more easily tested directly.
* internal functions so they can be more easily tested directly.
*/
contract StandardBridgeTester is StandardBridge { contract StandardBridgeTester is StandardBridge {
constructor(address payable _messenger, address payable _otherBridge) constructor(address payable _messenger, address payable _otherBridge)
StandardBridge(_messenger, _otherBridge) StandardBridge(_messenger, _otherBridge)
...@@ -34,10 +32,8 @@ contract StandardBridgeTester is StandardBridge { ...@@ -34,10 +32,8 @@ contract StandardBridgeTester is StandardBridge {
receive() external payable override {} receive() external payable override {}
} }
/** /// @title LegacyMintable
* @title LegacyMintable /// @notice Simple implementation of the legacy OptimismMintableERC20.
* @notice Simple implementation of the legacy OptimismMintableERC20.
*/
contract LegacyMintable is ERC20, ILegacyMintableERC20 { contract LegacyMintable is ERC20, ILegacyMintableERC20 {
constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {} constructor(string memory _name, string memory _ticker) ERC20(_name, _ticker) {}
...@@ -49,12 +45,10 @@ contract LegacyMintable is ERC20, ILegacyMintableERC20 { ...@@ -49,12 +45,10 @@ contract LegacyMintable is ERC20, ILegacyMintableERC20 {
function burn(address _from, uint256 _amount) external pure {} function burn(address _from, uint256 _amount) external pure {}
/** /// @notice Implements ERC165. This implementation should not be changed as
* @notice Implements ERC165. This implementation should not be changed as /// it is how the actual legacy optimism mintable token does the
* it is how the actual legacy optimism mintable token does the /// check. Allows for testing against code that is has been deployed,
* check. Allows for testing against code that is has been deployed, /// assuming different compiler version is no problem.
* assuming different compiler version is no problem.
*/
function supportsInterface(bytes4 _interfaceId) external pure returns (bool) { function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {
bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165 bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165
bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^ bytes4 secondSupportedInterface = ILegacyMintableERC20.l1Token.selector ^
...@@ -64,11 +58,9 @@ contract LegacyMintable is ERC20, ILegacyMintableERC20 { ...@@ -64,11 +58,9 @@ contract LegacyMintable is ERC20, ILegacyMintableERC20 {
} }
} }
/** /// @title StandardBridge_Stateless_Test
* @title StandardBridge_Stateless_Test /// @notice Tests internal functions that require no existing state or contract
* @notice Tests internal functions that require no existing state or contract /// interactions with the messenger.
* interactions with the messenger.
*/
contract StandardBridge_Stateless_Test is CommonTest { contract StandardBridge_Stateless_Test is CommonTest {
StandardBridgeTester internal bridge; StandardBridgeTester internal bridge;
OptimismMintableERC20 internal mintable; OptimismMintableERC20 internal mintable;
...@@ -94,12 +86,10 @@ contract StandardBridge_Stateless_Test is CommonTest { ...@@ -94,12 +86,10 @@ contract StandardBridge_Stateless_Test is CommonTest {
legacy = new LegacyMintable("Legacy", "LEG"); legacy = new LegacyMintable("Legacy", "LEG");
} }
/** /// @notice Test coverage for identifying OptimismMintableERC20 tokens.
* @notice Test coverage for identifying OptimismMintableERC20 tokens. /// This function should return true for both modern and legacy
* This function should return true for both modern and legacy /// OptimismMintableERC20 tokens and false for any accounts that
* OptimismMintableERC20 tokens and false for any accounts that /// do not implement the interface.
* do not implement the interface.
*/
function test_isOptimismMintableERC20_succeeds() external { function test_isOptimismMintableERC20_succeeds() external {
// Both the modern and legacy mintable tokens should return true // Both the modern and legacy mintable tokens should return true
assertTrue(bridge.isOptimismMintableERC20(address(mintable))); assertTrue(bridge.isOptimismMintableERC20(address(mintable)));
...@@ -111,10 +101,8 @@ contract StandardBridge_Stateless_Test is CommonTest { ...@@ -111,10 +101,8 @@ contract StandardBridge_Stateless_Test is CommonTest {
assertFalse(bridge.isOptimismMintableERC20(address(0x20))); assertFalse(bridge.isOptimismMintableERC20(address(0x20)));
} }
/** /// @notice Test coverage of isCorrectTokenPair under different types of
* @notice Test coverage of isCorrectTokenPair under different types of /// tokens.
* tokens.
*/
function test_isCorrectTokenPair_succeeds() external { function test_isCorrectTokenPair_succeeds() external {
// Modern + known to be correct remote token // Modern + known to be correct remote token
assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken())); assertTrue(bridge.isCorrectTokenPair(address(mintable), mintable.remoteToken()));
......
...@@ -5,73 +5,50 @@ import { L2StandardBridge } from "../L2/L2StandardBridge.sol"; ...@@ -5,73 +5,50 @@ import { L2StandardBridge } from "../L2/L2StandardBridge.sol";
import { Predeploys } from "../libraries/Predeploys.sol"; import { Predeploys } from "../libraries/Predeploys.sol";
import { SafeCall } from "../libraries/SafeCall.sol"; import { SafeCall } from "../libraries/SafeCall.sol";
/** /// @title FeeVault
* @title FeeVault /// @notice The FeeVault contract contains the basic logic for the various different vault contracts
* @notice The FeeVault contract contains the basic logic for the various different vault contracts /// used to hold fee revenue generated by the L2 system.
* used to hold fee revenue generated by the L2 system.
*/
abstract contract FeeVault { abstract contract FeeVault {
/** /// @notice Enum representing where the FeeVault withdraws funds to.
* @notice Enum representing where the FeeVault withdraws funds to. /// @custom:value L1 FeeVault withdraws funds to L1.
* @custom:value L1 FeeVault withdraws funds to L1. /// @custom:value L2 FeeVault withdraws funds to L2.
* @custom:value L2 FeeVault withdraws funds to L2.
*/
enum WithdrawalNetwork { enum WithdrawalNetwork {
L1, L1,
L2 L2
} }
/** /// @notice Minimum balance before a withdrawal can be triggered.
* @notice Minimum balance before a withdrawal can be triggered.
*/
uint256 public immutable MIN_WITHDRAWAL_AMOUNT; uint256 public immutable MIN_WITHDRAWAL_AMOUNT;
/** /// @notice Wallet that will receive the fees.
* @notice Wallet that will receive the fees.
*/
address public immutable RECIPIENT; address public immutable RECIPIENT;
/** /// @notice Network which the RECIPIENT will receive fees on.
* @notice Network which the RECIPIENT will receive fees on.
*/
WithdrawalNetwork public immutable WITHDRAWAL_NETWORK; WithdrawalNetwork public immutable WITHDRAWAL_NETWORK;
/** /// @notice The minimum gas limit for the FeeVault withdrawal transaction.
* @notice The minimum gas limit for the FeeVault withdrawal transaction.
*/
uint32 internal constant WITHDRAWAL_MIN_GAS = 35_000; uint32 internal constant WITHDRAWAL_MIN_GAS = 35_000;
/** /// @notice Total amount of wei processed by the contract.
* @notice Total amount of wei processed by the contract.
*/
uint256 public totalProcessed; uint256 public totalProcessed;
/** /// @notice Emitted each time a withdrawal occurs. This event will be deprecated
* @notice Emitted each time a withdrawal occurs. This event will be deprecated /// in favor of the Withdrawal event containing the WithdrawalNetwork parameter.
* in favor of the Withdrawal event containing the WithdrawalNetwork parameter. /// @param value Amount that was withdrawn (in wei).
* /// @param to Address that the funds were sent to.
* @param value Amount that was withdrawn (in wei). /// @param from Address that triggered the withdrawal.
* @param to Address that the funds were sent to.
* @param from Address that triggered the withdrawal.
*
*/
event Withdrawal(uint256 value, address to, address from); event Withdrawal(uint256 value, address to, address from);
/** /// @notice Emitted each time a withdrawal occurs.
* @notice Emitted each time a withdrawal occurs. /// @param value Amount that was withdrawn (in wei).
* /// @param to Address that the funds were sent to.
* @param value Amount that was withdrawn (in wei). /// @param from Address that triggered the withdrawal.
* @param to Address that the funds were sent to. /// @param withdrawalNetwork Network which the to address will receive funds on.
* @param from Address that triggered the withdrawal.
* @param withdrawalNetwork Network which the to address will receive funds on.
*/
event Withdrawal(uint256 value, address to, address from, WithdrawalNetwork withdrawalNetwork); event Withdrawal(uint256 value, address to, address from, WithdrawalNetwork withdrawalNetwork);
/** /// @param _recipient Wallet that will receive the fees.
* @param _recipient Wallet that will receive the fees. /// @param _minWithdrawalAmount Minimum balance for withdrawals.
* @param _minWithdrawalAmount Minimum balance for withdrawals. /// @param _withdrawalNetwork Network which the recipient will receive fees on.
* @param _withdrawalNetwork Network which the recipient will receive fees on.
*/
constructor( constructor(
address _recipient, address _recipient,
uint256 _minWithdrawalAmount, uint256 _minWithdrawalAmount,
...@@ -82,14 +59,10 @@ abstract contract FeeVault { ...@@ -82,14 +59,10 @@ abstract contract FeeVault {
WITHDRAWAL_NETWORK = _withdrawalNetwork; WITHDRAWAL_NETWORK = _withdrawalNetwork;
} }
/** /// @notice Allow the contract to receive ETH.
* @notice Allow the contract to receive ETH.
*/
receive() external payable {} receive() external payable {}
/** /// @notice Triggers a withdrawal of funds to the fee wallet on L1 or L2.
* @notice Triggers a withdrawal of funds to the fee wallet on L1 or L2.
*/
function withdraw() external { function withdraw() external {
require( require(
address(this).balance >= MIN_WITHDRAWAL_AMOUNT, address(this).balance >= MIN_WITHDRAWAL_AMOUNT,
......
...@@ -3,12 +3,10 @@ pragma solidity ^0.8.0; ...@@ -3,12 +3,10 @@ pragma solidity ^0.8.0;
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/** /// @title IOptimismMintableERC20
* @title IOptimismMintableERC20 /// @notice This interface is available on the OptimismMintableERC20 contract.
* @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a /// We declare it as a separate interface so that it can be used in
* separate interface so that it can be used in custom implementations of /// custom implementations of OptimismMintableERC20.
* OptimismMintableERC20.
*/
interface IOptimismMintableERC20 is IERC165 { interface IOptimismMintableERC20 is IERC165 {
function remoteToken() external view returns (address); function remoteToken() external view returns (address);
...@@ -19,12 +17,11 @@ interface IOptimismMintableERC20 is IERC165 { ...@@ -19,12 +17,11 @@ interface IOptimismMintableERC20 is IERC165 {
function burn(address _from, uint256 _amount) external; function burn(address _from, uint256 _amount) external;
} }
/** /// @custom:legacy
* @custom:legacy /// @title ILegacyMintableERC20
* @title ILegacyMintableERC20 /// @notice This interface was available on the legacy L2StandardERC20 contract.
* @notice This interface was available on the legacy L2StandardERC20 contract. It remains available /// It remains available on the OptimismMintableERC20 contract for
* on the OptimismMintableERC20 contract for backwards compatibility. /// backwards compatibility.
*/
interface ILegacyMintableERC20 is IERC165 { interface ILegacyMintableERC20 is IERC165 {
function l1Token() external view returns (address); function l1Token() external view returns (address);
......
...@@ -5,72 +5,46 @@ import { ...@@ -5,72 +5,46 @@ import {
IERC721Enumerable IERC721Enumerable
} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol"; } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
/** /// @title IOptimismMintableERC721
* @title IOptimismMintableERC721 /// @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.
* @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard. /// Tokens that follow this standard can be easily transferred across the ERC721 bridge.
* Tokens that follow this standard can be easily transferred across the ERC721 bridge.
*/
interface IOptimismMintableERC721 is IERC721Enumerable { interface IOptimismMintableERC721 is IERC721Enumerable {
/** /// @notice Emitted when a token is minted.
* @notice Emitted when a token is minted. /// @param account Address of the account the token was minted to.
* /// @param tokenId Token ID of the minted token.
* @param account Address of the account the token was minted to.
* @param tokenId Token ID of the minted token.
*/
event Mint(address indexed account, uint256 tokenId); event Mint(address indexed account, uint256 tokenId);
/** /// @notice Emitted when a token is burned.
* @notice Emitted when a token is burned. /// @param account Address of the account the token was burned from.
* /// @param tokenId Token ID of the burned token.
* @param account Address of the account the token was burned from.
* @param tokenId Token ID of the burned token.
*/
event Burn(address indexed account, uint256 tokenId); event Burn(address indexed account, uint256 tokenId);
/** /// @notice Mints some token ID for a user, checking first that contract recipients
* @notice Mints some token ID for a user, checking first that contract recipients /// are aware of the ERC721 protocol to prevent tokens from being forever locked.
* are aware of the ERC721 protocol to prevent tokens from being forever locked. /// @param _to Address of the user to mint the token for.
* /// @param _tokenId Token ID to mint.
* @param _to Address of the user to mint the token for.
* @param _tokenId Token ID to mint.
*/
function safeMint(address _to, uint256 _tokenId) external; function safeMint(address _to, uint256 _tokenId) external;
/** /// @notice Burns a token ID from a user.
* @notice Burns a token ID from a user. /// @param _from Address of the user to burn the token from.
* /// @param _tokenId Token ID to burn.
* @param _from Address of the user to burn the token from.
* @param _tokenId Token ID to burn.
*/
function burn(address _from, uint256 _tokenId) external; function burn(address _from, uint256 _tokenId) external;
/** /// @notice Chain ID of the chain where the remote token is deployed.
* @notice Chain ID of the chain where the remote token is deployed.
*/
function REMOTE_CHAIN_ID() external view returns (uint256); function REMOTE_CHAIN_ID() external view returns (uint256);
/** /// @notice Address of the token on the remote domain.
* @notice Address of the token on the remote domain.
*/
function REMOTE_TOKEN() external view returns (address); function REMOTE_TOKEN() external view returns (address);
/** /// @notice Address of the ERC721 bridge on this network.
* @notice Address of the ERC721 bridge on this network.
*/
function BRIDGE() external view returns (address); function BRIDGE() external view returns (address);
/** /// @notice Chain ID of the chain where the remote token is deployed.
* @notice Chain ID of the chain where the remote token is deployed.
*/
function remoteChainId() external view returns (uint256); function remoteChainId() external view returns (uint256);
/** /// @notice Address of the token on the remote domain.
* @notice Address of the token on the remote domain.
*/
function remoteToken() external view returns (address); function remoteToken() external view returns (address);
/** /// @notice Address of the ERC721 bridge on this network.
* @notice Address of the ERC721 bridge on this network.
*/
function bridge() external view returns (address); function bridge() external view returns (address);
} }
...@@ -6,73 +6,53 @@ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol ...@@ -6,73 +6,53 @@ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol
import { ILegacyMintableERC20, IOptimismMintableERC20 } from "./IOptimismMintableERC20.sol"; import { ILegacyMintableERC20, IOptimismMintableERC20 } from "./IOptimismMintableERC20.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "../universal/Semver.sol";
/** /// @title OptimismMintableERC20
* @title OptimismMintableERC20 /// @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed
* @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed /// to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to
* to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to /// use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.
* use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa. /// Designed to be backwards compatible with the older StandardL2ERC20 token which was only
* Designed to be backwards compatible with the older StandardL2ERC20 token which was only /// meant for use on L2.
* meant for use on L2.
*/
contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver { contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, Semver {
/** /// @notice Address of the corresponding version of this token on the remote chain.
* @notice Address of the corresponding version of this token on the remote chain.
*/
address public immutable REMOTE_TOKEN; address public immutable REMOTE_TOKEN;
/** /// @notice Address of the StandardBridge on this network.
* @notice Address of the StandardBridge on this network.
*/
address public immutable BRIDGE; address public immutable BRIDGE;
/** /// @notice Emitted whenever tokens are minted for an account.
* @notice Emitted whenever tokens are minted for an account. /// @param account Address of the account tokens are being minted for.
* /// @param amount Amount of tokens minted.
* @param account Address of the account tokens are being minted for.
* @param amount Amount of tokens minted.
*/
event Mint(address indexed account, uint256 amount); event Mint(address indexed account, uint256 amount);
/** /// @notice Emitted whenever tokens are burned from an account.
* @notice Emitted whenever tokens are burned from an account. /// @param account Address of the account tokens are being burned from.
* /// @param amount Amount of tokens burned.
* @param account Address of the account tokens are being burned from.
* @param amount Amount of tokens burned.
*/
event Burn(address indexed account, uint256 amount); event Burn(address indexed account, uint256 amount);
/** /// @notice A modifier that only allows the bridge to call
* @notice A modifier that only allows the bridge to call
*/
modifier onlyBridge() { modifier onlyBridge() {
require(msg.sender == BRIDGE, "OptimismMintableERC20: only bridge can mint and burn"); require(msg.sender == BRIDGE, "OptimismMintableERC20: only bridge can mint and burn");
_; _;
} }
/** /// @custom:semver 1.0.1
* @custom:semver 1.0.0 /// @param _bridge Address of the L2 standard bridge.
* /// @param _remoteToken Address of the corresponding L1 token.
* @param _bridge Address of the L2 standard bridge. /// @param _name ERC20 name.
* @param _remoteToken Address of the corresponding L1 token. /// @param _symbol ERC20 symbol.
* @param _name ERC20 name.
* @param _symbol ERC20 symbol.
*/
constructor( constructor(
address _bridge, address _bridge,
address _remoteToken, address _remoteToken,
string memory _name, string memory _name,
string memory _symbol string memory _symbol
) ERC20(_name, _symbol) Semver(1, 0, 0) { ) ERC20(_name, _symbol) Semver(1, 0, 1) {
REMOTE_TOKEN = _remoteToken; REMOTE_TOKEN = _remoteToken;
BRIDGE = _bridge; BRIDGE = _bridge;
} }
/** /// @notice Allows the StandardBridge on this network to mint tokens.
* @notice Allows the StandardBridge on this network to mint tokens. /// @param _to Address to mint tokens to.
* /// @param _amount Amount of tokens to mint.
* @param _to Address to mint tokens to.
* @param _amount Amount of tokens to mint.
*/
function mint(address _to, uint256 _amount) function mint(address _to, uint256 _amount)
external external
virtual virtual
...@@ -83,12 +63,9 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ...@@ -83,12 +63,9 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20,
emit Mint(_to, _amount); emit Mint(_to, _amount);
} }
/** /// @notice Allows the StandardBridge on this network to burn tokens.
* @notice Allows the StandardBridge on this network to burn tokens. /// @param _from Address to burn tokens from.
* /// @param _amount Amount of tokens to burn.
* @param _from Address to burn tokens from.
* @param _amount Amount of tokens to burn.
*/
function burn(address _from, uint256 _amount) function burn(address _from, uint256 _amount)
external external
virtual virtual
...@@ -99,13 +76,9 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ...@@ -99,13 +76,9 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20,
emit Burn(_from, _amount); emit Burn(_from, _amount);
} }
/** /// @notice ERC165 interface check function.
* @notice ERC165 interface check function. /// @param _interfaceId Interface ID to check.
* /// @return Whether or not the interface is supported by this contract.
* @param _interfaceId Interface ID to check.
*
* @return Whether or not the interface is supported by this contract.
*/
function supportsInterface(bytes4 _interfaceId) external pure returns (bool) { function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {
bytes4 iface1 = type(IERC165).interfaceId; bytes4 iface1 = type(IERC165).interfaceId;
// Interface corresponding to the legacy L2StandardERC20. // Interface corresponding to the legacy L2StandardERC20.
...@@ -115,34 +88,26 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ...@@ -115,34 +88,26 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20,
return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3; return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;
} }
/** /// @custom:legacy
* @custom:legacy /// @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.
* @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.
*/
function l1Token() public view returns (address) { function l1Token() public view returns (address) {
return REMOTE_TOKEN; return REMOTE_TOKEN;
} }
/** /// @custom:legacy
* @custom:legacy /// @notice Legacy getter for the bridge. Use BRIDGE going forward.
* @notice Legacy getter for the bridge. Use BRIDGE going forward.
*/
function l2Bridge() public view returns (address) { function l2Bridge() public view returns (address) {
return BRIDGE; return BRIDGE;
} }
/** /// @custom:legacy
* @custom:legacy /// @notice Legacy getter for REMOTE_TOKEN.
* @notice Legacy getter for REMOTE_TOKEN.
*/
function remoteToken() public view returns (address) { function remoteToken() public view returns (address) {
return REMOTE_TOKEN; return REMOTE_TOKEN;
} }
/** /// @custom:legacy
* @custom:legacy /// @notice Legacy getter for BRIDGE.
* @notice Legacy getter for BRIDGE.
*/
function bridge() public view returns (address) { function bridge() public view returns (address) {
return BRIDGE; return BRIDGE;
} }
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
/* Contract Imports */
import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol"; import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol";
import { Semver } from "./Semver.sol"; import { Semver } from "./Semver.sol";
/** /// @custom:proxied
* @custom:proxied /// @custom:predeployed 0x4200000000000000000000000000000000000012
* @custom:predeployed 0x4200000000000000000000000000000000000012 /// @title OptimismMintableERC20Factory
* @title OptimismMintableERC20Factory /// @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20
* @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20 /// contracts on the network it's deployed to. Simplifies the deployment process for users
* 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
* who may be less familiar with deploying smart contracts. Designed to be backwards /// compatible with the older StandardL2ERC20Factory contract.
* compatible with the older StandardL2ERC20Factory contract.
*/
contract OptimismMintableERC20Factory is Semver { contract OptimismMintableERC20Factory is Semver {
/** /// @notice Address of the StandardBridge on this chain.
* @notice Address of the StandardBridge on this chain.
*/
address public immutable BRIDGE; address public immutable BRIDGE;
/** /// @custom:legacy
* @custom:legacy /// @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer
* @notice Emitted whenever a new OptimismMintableERC20 is created. Legacy version of the newer /// OptimismMintableERC20Created event. We recommend relying on that event instead.
* OptimismMintableERC20Created event. We recommend relying on that event instead. /// @param remoteToken Address of the token on the remote chain.
* /// @param localToken Address of the created token on the local chain.
* @param remoteToken Address of the token on the remote chain.
* @param localToken Address of the created token on the local chain.
*/
event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken); event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken);
/** /// @notice Emitted whenever a new OptimismMintableERC20 is created.
* @notice Emitted whenever a new OptimismMintableERC20 is created. /// @param localToken Address of the created token on the local chain.
* /// @param remoteToken Address of the corresponding token on the remote chain.
* @param localToken Address of the created token on the local chain. /// @param deployer Address of the account that deployed the token.
* @param remoteToken Address of the corresponding token on the remote chain.
* @param deployer Address of the account that deployed the token.
*/
event OptimismMintableERC20Created( event OptimismMintableERC20Created(
address indexed localToken, address indexed localToken,
address indexed remoteToken, address indexed remoteToken,
address deployer address deployer
); );
/** /// @custom:semver 1.1.1
* @custom:semver 1.1.0 /// @notice The semver MUST be bumped any time that there is a change in
* /// the OptimismMintableERC20 token contract since this contract
* @notice The semver MUST be bumped any time that there is a change in /// is responsible for deploying OptimismMintableERC20 contracts.
* the OptimismMintableERC20 token contract since this contract /// @param _bridge Address of the StandardBridge on this chain.
* is responsible for deploying OptimismMintableERC20 contracts. constructor(address _bridge) Semver(1, 1, 1) {
*
* @param _bridge Address of the StandardBridge on this chain.
*/
constructor(address _bridge) Semver(1, 1, 0) {
BRIDGE = _bridge; BRIDGE = _bridge;
} }
/** /// @custom:legacy
* @custom:legacy /// @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the
* @notice Creates an instance of the OptimismMintableERC20 contract. Legacy version of the /// newer createOptimismMintableERC20 function, which has a more intuitive name.
* newer createOptimismMintableERC20 function, which has a more intuitive name. /// @param _remoteToken Address of the token on the remote chain.
* /// @param _name ERC20 name.
* @param _remoteToken Address of the token on the remote chain. /// @param _symbol ERC20 symbol.
* @param _name ERC20 name. /// @return Address of the newly created token.
* @param _symbol ERC20 symbol.
*
* @return Address of the newly created token.
*/
function createStandardL2Token( function createStandardL2Token(
address _remoteToken, address _remoteToken,
string memory _name, string memory _name,
...@@ -75,15 +56,11 @@ contract OptimismMintableERC20Factory is Semver { ...@@ -75,15 +56,11 @@ contract OptimismMintableERC20Factory is Semver {
return createOptimismMintableERC20(_remoteToken, _name, _symbol); return createOptimismMintableERC20(_remoteToken, _name, _symbol);
} }
/** /// @notice Creates an instance of the OptimismMintableERC20 contract.
* @notice Creates an instance of the OptimismMintableERC20 contract. /// @param _remoteToken Address of the token on the remote chain.
* /// @param _name ERC20 name.
* @param _remoteToken Address of the token on the remote chain. /// @param _symbol ERC20 symbol.
* @param _name ERC20 name. /// @return Address of the newly created token.
* @param _symbol ERC20 symbol.
*
* @return Address of the newly created token.
*/
function createOptimismMintableERC20( function createOptimismMintableERC20(
address _remoteToken, address _remoteToken,
string memory _name, string memory _name,
......
...@@ -10,57 +10,42 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; ...@@ -10,57 +10,42 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { IOptimismMintableERC721 } from "./IOptimismMintableERC721.sol"; import { IOptimismMintableERC721 } from "./IOptimismMintableERC721.sol";
import { Semver } from "../universal/Semver.sol"; import { Semver } from "../universal/Semver.sol";
/** /// @title OptimismMintableERC721
* @title OptimismMintableERC721 /// @notice This contract is the remote representation for some token that lives on another network,
* @notice This contract is the remote representation for some token that lives on another network, /// typically an Optimism representation of an Ethereum-based token. Standard reference
* typically an Optimism representation of an Ethereum-based token. Standard reference /// implementation that can be extended or modified according to your needs.
* implementation that can be extended or modified according to your needs.
*/
contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721, Semver { contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721, Semver {
/** /// @inheritdoc IOptimismMintableERC721
* @inheritdoc IOptimismMintableERC721
*/
uint256 public immutable REMOTE_CHAIN_ID; uint256 public immutable REMOTE_CHAIN_ID;
/** /// @inheritdoc IOptimismMintableERC721
* @inheritdoc IOptimismMintableERC721
*/
address public immutable REMOTE_TOKEN; address public immutable REMOTE_TOKEN;
/** /// @inheritdoc IOptimismMintableERC721
* @inheritdoc IOptimismMintableERC721
*/
address public immutable BRIDGE; address public immutable BRIDGE;
/** /// @notice Base token URI for this token.
* @notice Base token URI for this token.
*/
string public baseTokenURI; string public baseTokenURI;
/** /// @notice Modifier that prevents callers other than the bridge from calling the function.
* @notice Modifier that prevents callers other than the bridge from calling the function.
*/
modifier onlyBridge() { modifier onlyBridge() {
require(msg.sender == BRIDGE, "OptimismMintableERC721: only bridge can call this function"); require(msg.sender == BRIDGE, "OptimismMintableERC721: only bridge can call this function");
_; _;
} }
/** /// @custom:semver 1.1.1
* @custom:semver 1.1.0 /// @param _bridge Address of the bridge on this network.
* /// @param _remoteChainId Chain ID where the remote token is deployed.
* @param _bridge Address of the bridge on this network. /// @param _remoteToken Address of the corresponding token on the other network.
* @param _remoteChainId Chain ID where the remote token is deployed. /// @param _name ERC721 name.
* @param _remoteToken Address of the corresponding token on the other network. /// @param _symbol ERC721 symbol.
* @param _name ERC721 name.
* @param _symbol ERC721 symbol.
*/
constructor( constructor(
address _bridge, address _bridge,
uint256 _remoteChainId, uint256 _remoteChainId,
address _remoteToken, address _remoteToken,
string memory _name, string memory _name,
string memory _symbol string memory _symbol
) ERC721(_name, _symbol) Semver(1, 1, 0) { ) ERC721(_name, _symbol) Semver(1, 1, 1) {
require(_bridge != address(0), "OptimismMintableERC721: bridge cannot be address(0)"); require(_bridge != address(0), "OptimismMintableERC721: bridge cannot be address(0)");
require(_remoteChainId != 0, "OptimismMintableERC721: remote chain id cannot be zero"); require(_remoteChainId != 0, "OptimismMintableERC721: remote chain id cannot be zero");
require( require(
...@@ -85,52 +70,38 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721, Se ...@@ -85,52 +70,38 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721, Se
); );
} }
/** /// @inheritdoc IOptimismMintableERC721
* @inheritdoc IOptimismMintableERC721
*/
function remoteChainId() external view returns (uint256) { function remoteChainId() external view returns (uint256) {
return REMOTE_CHAIN_ID; return REMOTE_CHAIN_ID;
} }
/** /// @inheritdoc IOptimismMintableERC721
* @inheritdoc IOptimismMintableERC721
*/
function remoteToken() external view returns (address) { function remoteToken() external view returns (address) {
return REMOTE_TOKEN; return REMOTE_TOKEN;
} }
/** /// @inheritdoc IOptimismMintableERC721
* @inheritdoc IOptimismMintableERC721
*/
function bridge() external view returns (address) { function bridge() external view returns (address) {
return BRIDGE; return BRIDGE;
} }
/** /// @inheritdoc IOptimismMintableERC721
* @inheritdoc IOptimismMintableERC721
*/
function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge { function safeMint(address _to, uint256 _tokenId) external virtual onlyBridge {
_safeMint(_to, _tokenId); _safeMint(_to, _tokenId);
emit Mint(_to, _tokenId); emit Mint(_to, _tokenId);
} }
/** /// @inheritdoc IOptimismMintableERC721
* @inheritdoc IOptimismMintableERC721
*/
function burn(address _from, uint256 _tokenId) external virtual onlyBridge { function burn(address _from, uint256 _tokenId) external virtual onlyBridge {
_burn(_tokenId); _burn(_tokenId);
emit Burn(_from, _tokenId); emit Burn(_from, _tokenId);
} }
/** /// @notice Checks if a given interface ID is supported by this contract.
* @notice Checks if a given interface ID is supported by this contract. /// @param _interfaceId The interface ID to check.
* /// @return True if the interface ID is supported, false otherwise.
* @param _interfaceId The interface ID to check.
*
* @return True if the interface ID is supported, false otherwise.
*/
function supportsInterface(bytes4 _interfaceId) function supportsInterface(bytes4 _interfaceId)
public public
view view
...@@ -141,11 +112,8 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721, Se ...@@ -141,11 +112,8 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721, Se
return _interfaceId == iface || super.supportsInterface(_interfaceId); return _interfaceId == iface || super.supportsInterface(_interfaceId);
} }
/** /// @notice Returns the base token URI.
* @notice Returns the base token URI. /// @return Base token URI.
*
* @return Base token URI.
*/
function _baseURI() internal view virtual override returns (string memory) { function _baseURI() internal view virtual override returns (string memory) {
return baseTokenURI; return baseTokenURI;
} }
......
...@@ -4,60 +4,43 @@ pragma solidity 0.8.15; ...@@ -4,60 +4,43 @@ pragma solidity 0.8.15;
import { OptimismMintableERC721 } from "./OptimismMintableERC721.sol"; import { OptimismMintableERC721 } from "./OptimismMintableERC721.sol";
import { Semver } from "./Semver.sol"; import { Semver } from "./Semver.sol";
/** /// @title OptimismMintableERC721Factory
* @title OptimismMintableERC721Factory /// @notice Factory contract for creating OptimismMintableERC721 contracts.
* @notice Factory contract for creating OptimismMintableERC721 contracts.
*/
contract OptimismMintableERC721Factory is Semver { contract OptimismMintableERC721Factory is Semver {
/** /// @notice Address of the ERC721 bridge on this network.
* @notice Address of the ERC721 bridge on this network.
*/
address public immutable BRIDGE; address public immutable BRIDGE;
/** /// @notice Chain ID for the remote network.
* @notice Chain ID for the remote network.
*/
uint256 public immutable REMOTE_CHAIN_ID; uint256 public immutable REMOTE_CHAIN_ID;
/** /// @notice Tracks addresses created by this factory.
* @notice Tracks addresses created by this factory.
*/
mapping(address => bool) public isOptimismMintableERC721; mapping(address => bool) public isOptimismMintableERC721;
/** /// @notice Emitted whenever a new OptimismMintableERC721 contract is created.
* @notice Emitted whenever a new OptimismMintableERC721 contract is created. /// @param localToken Address of the token on the this domain.
* /// @param remoteToken Address of the token on the remote domain.
* @param localToken Address of the token on the this domain. /// @param deployer Address of the initiator of the deployment
* @param remoteToken Address of the token on the remote domain.
* @param deployer Address of the initiator of the deployment
*/
event OptimismMintableERC721Created( event OptimismMintableERC721Created(
address indexed localToken, address indexed localToken,
address indexed remoteToken, address indexed remoteToken,
address deployer address deployer
); );
/** /// @custom:semver 1.2.1
* @custom:semver 1.2.0 /// @notice The semver MUST be bumped any time that there is a change in
* @notice The semver MUST be bumped any time that there is a change in /// the OptimismMintableERC721 token contract since this contract
* the OptimismMintableERC721 token contract since this contract /// is responsible for deploying OptimismMintableERC721 contracts.
* is responsible for deploying OptimismMintableERC721 contracts. /// @param _bridge Address of the ERC721 bridge on this network.
* /// @param _remoteChainId Chain ID for the remote network.
* @param _bridge Address of the ERC721 bridge on this network. constructor(address _bridge, uint256 _remoteChainId) Semver(1, 2, 1) {
* @param _remoteChainId Chain ID for the remote network.
*/
constructor(address _bridge, uint256 _remoteChainId) Semver(1, 2, 0) {
BRIDGE = _bridge; BRIDGE = _bridge;
REMOTE_CHAIN_ID = _remoteChainId; REMOTE_CHAIN_ID = _remoteChainId;
} }
/** /// @notice Creates an instance of the standard ERC721.
* @notice Creates an instance of the standard ERC721. /// @param _remoteToken Address of the corresponding token on the other domain.
* /// @param _name ERC721 name.
* @param _remoteToken Address of the corresponding token on the other domain. /// @param _symbol ERC721 symbol.
* @param _name ERC721 name.
* @param _symbol ERC721 symbol.
*/
function createOptimismMintableERC721( function createOptimismMintableERC721(
address _remoteToken, address _remoteToken,
string memory _name, string memory _name,
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
/** /// @title Proxy
* @title Proxy /// @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or
* @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or /// if the caller is address(0), meaning that the call originated from an off-chain
* if the caller is address(0), meaning that the call originated from an off-chain /// simulation.
* simulation.
*/
contract Proxy { contract Proxy {
/** /// @notice The storage slot that holds the address of the implementation.
* @notice The storage slot that holds the address of the implementation. /// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
* bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
*/
bytes32 internal constant IMPLEMENTATION_KEY = bytes32 internal constant IMPLEMENTATION_KEY =
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/** /// @notice The storage slot that holds the address of the owner.
* @notice The storage slot that holds the address of the owner. /// bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
* bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
*/
bytes32 internal constant OWNER_KEY = bytes32 internal constant OWNER_KEY =
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/** /// @notice An event that is emitted each time the implementation is changed. This event is part
* @notice An event that is emitted each time the implementation is changed. This event is part /// of the EIP-1967 specification.
* of the EIP-1967 specification. /// @param implementation The address of the implementation contract
*
* @param implementation The address of the implementation contract
*/
event Upgraded(address indexed implementation); event Upgraded(address indexed implementation);
/** /// @notice An event that is emitted each time the owner is upgraded. This event is part of the
* @notice An event that is emitted each time the owner is upgraded. This event is part of the /// EIP-1967 specification.
* EIP-1967 specification. /// @param previousAdmin The previous owner of the contract
* /// @param newAdmin The new owner of the contract
* @param previousAdmin The previous owner of the contract
* @param newAdmin The new owner of the contract
*/
event AdminChanged(address previousAdmin, address newAdmin); event AdminChanged(address previousAdmin, address newAdmin);
/** /// @notice A modifier that reverts if not called by the owner or by address(0) to allow
* @notice A modifier that reverts if not called by the owner or by address(0) to allow /// eth_call to interact with this proxy without needing to use low-level storage
* eth_call to interact with this proxy without needing to use low-level storage /// inspection. We assume that nobody is able to trigger calls from address(0) during
* inspection. We assume that nobody is able to trigger calls from address(0) during /// normal EVM execution.
* normal EVM execution.
*/
modifier proxyCallIfNotAdmin() { modifier proxyCallIfNotAdmin() {
if (msg.sender == _getAdmin() || msg.sender == address(0)) { if (msg.sender == _getAdmin() || msg.sender == address(0)) {
_; _;
...@@ -54,14 +40,11 @@ contract Proxy { ...@@ -54,14 +40,11 @@ contract Proxy {
} }
} }
/** /// @notice Sets the initial admin during contract deployment. Admin address is stored at the
* @notice Sets the initial admin during contract deployment. Admin address is stored at the /// EIP-1967 admin storage slot so that accidental storage collision with the
* EIP-1967 admin storage slot so that accidental storage collision with the /// implementation is not possible.
* implementation is not possible. /// @param _admin Address of the initial contract admin. Admin as the ability to access the
* /// transparent proxy interface.
* @param _admin Address of the initial contract admin. Admin as the ability to access the
* transparent proxy interface.
*/
constructor(address _admin) { constructor(address _admin) {
_changeAdmin(_admin); _changeAdmin(_admin);
} }
...@@ -78,23 +61,17 @@ contract Proxy { ...@@ -78,23 +61,17 @@ contract Proxy {
_doProxyCall(); _doProxyCall();
} }
/** /// @notice Set the implementation contract address. The code at the given address will execute
* @notice Set the implementation contract address. The code at the given address will execute /// when this contract is called.
* when this contract is called. /// @param _implementation Address of the implementation contract.
*
* @param _implementation Address of the implementation contract.
*/
function upgradeTo(address _implementation) public virtual proxyCallIfNotAdmin { function upgradeTo(address _implementation) public virtual proxyCallIfNotAdmin {
_setImplementation(_implementation); _setImplementation(_implementation);
} }
/** /// @notice Set the implementation and call a function in a single transaction. Useful to ensure
* @notice Set the implementation and call a function in a single transaction. Useful to ensure /// atomic execution of initialization-based upgrades.
* atomic execution of initialization-based upgrades. /// @param _implementation Address of the implementation contract.
* /// @param _data Calldata to delegatecall the new implementation with.
* @param _implementation Address of the implementation contract.
* @param _data Calldata to delegatecall the new implementation with.
*/
function upgradeToAndCall(address _implementation, bytes calldata _data) function upgradeToAndCall(address _implementation, bytes calldata _data)
public public
payable payable
...@@ -108,38 +85,26 @@ contract Proxy { ...@@ -108,38 +85,26 @@ contract Proxy {
return returndata; return returndata;
} }
/** /// @notice Changes the owner of the proxy contract. Only callable by the owner.
* @notice Changes the owner of the proxy contract. Only callable by the owner. /// @param _admin New owner of the proxy contract.
*
* @param _admin New owner of the proxy contract.
*/
function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin { function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin {
_changeAdmin(_admin); _changeAdmin(_admin);
} }
/** /// @notice Gets the owner of the proxy contract.
* @notice Gets the owner of the proxy contract. /// @return Owner address.
*
* @return Owner address.
*/
function admin() public virtual proxyCallIfNotAdmin returns (address) { function admin() public virtual proxyCallIfNotAdmin returns (address) {
return _getAdmin(); return _getAdmin();
} }
/** //// @notice Queries the implementation address.
* @notice Queries the implementation address. /// @return Implementation address.
*
* @return Implementation address.
*/
function implementation() public virtual proxyCallIfNotAdmin returns (address) { function implementation() public virtual proxyCallIfNotAdmin returns (address) {
return _getImplementation(); return _getImplementation();
} }
/** /// @notice Sets the implementation address.
* @notice Sets the implementation address. /// @param _implementation New implementation address.
*
* @param _implementation New implementation address.
*/
function _setImplementation(address _implementation) internal { function _setImplementation(address _implementation) internal {
assembly { assembly {
sstore(IMPLEMENTATION_KEY, _implementation) sstore(IMPLEMENTATION_KEY, _implementation)
...@@ -147,11 +112,8 @@ contract Proxy { ...@@ -147,11 +112,8 @@ contract Proxy {
emit Upgraded(_implementation); emit Upgraded(_implementation);
} }
/** /// @notice Changes the owner of the proxy contract.
* @notice Changes the owner of the proxy contract. /// @param _admin New owner of the proxy contract.
*
* @param _admin New owner of the proxy contract.
*/
function _changeAdmin(address _admin) internal { function _changeAdmin(address _admin) internal {
address previous = _getAdmin(); address previous = _getAdmin();
assembly { assembly {
...@@ -160,9 +122,7 @@ contract Proxy { ...@@ -160,9 +122,7 @@ contract Proxy {
emit AdminChanged(previous, _admin); emit AdminChanged(previous, _admin);
} }
/** /// @notice Performs the proxy call via a delegatecall.
* @notice Performs the proxy call via a delegatecall.
*/
function _doProxyCall() internal { function _doProxyCall() internal {
address impl = _getImplementation(); address impl = _getImplementation();
require(impl != address(0), "Proxy: implementation not initialized"); require(impl != address(0), "Proxy: implementation not initialized");
...@@ -189,11 +149,8 @@ contract Proxy { ...@@ -189,11 +149,8 @@ contract Proxy {
} }
} }
/** /// @notice Queries the implementation address.
* @notice Queries the implementation address. /// @return Implementation address.
*
* @return Implementation address.
*/
function _getImplementation() internal view returns (address) { function _getImplementation() internal view returns (address) {
address impl; address impl;
assembly { assembly {
...@@ -202,11 +159,8 @@ contract Proxy { ...@@ -202,11 +159,8 @@ contract Proxy {
return impl; return impl;
} }
/** /// @notice Queries the owner of the proxy contract.
* @notice Queries the owner of the proxy contract. /// @return Owner address.
*
* @return Owner address.
*/
function _getAdmin() internal view returns (address) { function _getAdmin() internal view returns (address) {
address owner; address owner;
assembly { assembly {
......
...@@ -3,31 +3,21 @@ pragma solidity ^0.8.0; ...@@ -3,31 +3,21 @@ pragma solidity ^0.8.0;
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
/** /// @title Semver
* @title Semver /// @notice Semver is a simple contract for managing contract versions.
* @notice Semver is a simple contract for managing contract versions.
*/
contract Semver { contract Semver {
/** /// @notice Contract version number (major).
* @notice Contract version number (major).
*/
uint256 private immutable MAJOR_VERSION; uint256 private immutable MAJOR_VERSION;
/** /// @notice Contract version number (minor).
* @notice Contract version number (minor).
*/
uint256 private immutable MINOR_VERSION; uint256 private immutable MINOR_VERSION;
/** /// @notice Contract version number (patch).
* @notice Contract version number (patch).
*/
uint256 private immutable PATCH_VERSION; uint256 private immutable PATCH_VERSION;
/** /// @param _major Version number (major).
* @param _major Version number (major). /// @param _minor Version number (minor).
* @param _minor Version number (minor). /// @param _patch Version number (patch).
* @param _patch Version number (patch).
*/
constructor( constructor(
uint256 _major, uint256 _major,
uint256 _minor, uint256 _minor,
...@@ -38,11 +28,8 @@ contract Semver { ...@@ -38,11 +28,8 @@ contract Semver {
PATCH_VERSION = _patch; PATCH_VERSION = _patch;
} }
/** /// @notice Returns the full semver contract version.
* @notice Returns the full semver contract version. /// @return Semver contract version as a string.
*
* @return Semver contract version as a string.
*/
function version() public view returns (string memory) { function version() public view returns (string memory) {
return return
string( string(
......
...@@ -428,7 +428,7 @@ const check = { ...@@ -428,7 +428,7 @@ const check = {
await assertSemver( await assertSemver(
OptimismMintableERC20Factory, OptimismMintableERC20Factory,
'OptimismMintableERC20Factory', 'OptimismMintableERC20Factory',
'1.1.0' '1.1.1'
) )
const BRIDGE = await OptimismMintableERC20Factory.BRIDGE() const BRIDGE = await OptimismMintableERC20Factory.BRIDGE()
...@@ -554,7 +554,7 @@ const check = { ...@@ -554,7 +554,7 @@ const check = {
await assertSemver( await assertSemver(
OptimismMintableERC721Factory, OptimismMintableERC721Factory,
'OptimismMintableERC721Factory', 'OptimismMintableERC721Factory',
'1.2.0' '1.2.1'
) )
const BRIDGE = await OptimismMintableERC721Factory.BRIDGE() const BRIDGE = await OptimismMintableERC721Factory.BRIDGE()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment