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