Commit 68c2e0d3 authored by smartcontracts's avatar smartcontracts Committed by GitHub

feat: make CommonTest generic over Solidity versions (#13368)

Makes CommonTest generic over Solidity versions by removing
direct dependencies on 0.8.15 contracts. Updates some interfaces
to achieve this.
parent 12862e7b
......@@ -84,18 +84,12 @@ rules:
pattern-regex: function\s+\w+\s*\(\s*([^)]*?\b\w+\s+(?!_)(?!memory\b)(?!calldata\b)(?!storage\b)(?!payable\b)\w+\s*(?=,|\)))
paths:
exclude:
- packages/contracts-bedrock/interfaces/universal/IOptimismMintableERC721.sol
- packages/contracts-bedrock/interfaces/universal/IWETH98.sol
- packages/contracts-bedrock/interfaces/dispute/IDelayedWETH.sol
- op-chain-ops/script/testdata/scripts/ScriptExample.s.sol
- packages/contracts-bedrock/test
- packages/contracts-bedrock/interfaces
- packages/contracts-bedrock/scripts/libraries/Solarray.sol
- packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol
- packages/contracts-bedrock/interfaces/universal/IWETH.sol
- packages/contracts-bedrock/src/universal/WETH98.sol
- packages/contracts-bedrock/interfaces/L2/ISuperchainWETH.sol
- packages/contracts-bedrock/src/L2/SuperchainWETH.sol
- packages/contracts-bedrock/interfaces/governance/IGovernanceToken.sol
- packages/contracts-bedrock/src/governance/GovernanceToken.sol
- id: sol-style-return-arg-fmt
......@@ -107,11 +101,10 @@ rules:
exclude:
- packages/contracts-bedrock/interfaces/dispute/IDelayedWETH.sol
- op-chain-ops/script/testdata/scripts/ScriptExample.s.sol
- packages/contracts-bedrock/interfaces
- packages/contracts-bedrock/test/safe-tools
- packages/contracts-bedrock/scripts/libraries/Solarray.sol
- packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol
- packages/contracts-bedrock/interfaces/dispute/IPermissionedDisputeGame.sol
- packages/contracts-bedrock/interfaces/dispute/IFaultDisputeGame.sol
- id: sol-style-doc-comment
languages: [solidity]
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ILegacyMintableERC20Full {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Burn(address indexed _account, uint256 _amount);
event Mint(address indexed _account, uint256 _amount);
event Transfer(address indexed from, address indexed to, uint256 value);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function burn(address _from, uint256 _amount) external;
function decimals() external view returns (uint8);
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
function l1Token() external view returns (address);
function l2Bridge() external view returns (address);
function mint(address _to, uint256 _amount) external;
function name() external view returns (string memory);
function supportsInterface(bytes4 _interfaceId) external pure returns (bool);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function __constructor__(address _l2Bridge, address _l1Token, string memory _name, string memory _symbol) external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOptimismMintableERC20Full {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Burn(address indexed account, uint256 amount);
event Mint(address indexed account, uint256 amount);
event Transfer(address indexed from, address indexed to, uint256 value);
function BRIDGE() external view returns (address);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT2() external pure returns (address);
function REMOTE_TOKEN() external view returns (address);
function allowance(address _owner, address _spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function bridge() external view returns (address);
function burn(address _from, uint256 _amount) external;
function decimals() external view returns (uint8);
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
function l1Token() external view returns (address);
function l2Bridge() external view returns (address);
function mint(address _to, uint256 _amount) external;
function name() external view returns (string memory);
function nonces(address owner) external view returns (uint256);
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
function remoteToken() external view returns (address);
function supportsInterface(bytes4 _interfaceId) external pure returns (bool);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function version() external view returns (string memory);
function __constructor__(address _bridge, address _remoteToken, string memory _name, string memory _symbol, uint8 _decimals) external;
}
......@@ -12,8 +12,8 @@
"sourceCodeHash": "0x48f4e1db42f82490e91fd33b05117b05c072444ed53bbd4e06e742d330a422bb"
},
"src/L1/L1StandardBridge.sol": {
"initCodeHash": "0x9037e1930606d8cd092738bf28dda74e8f993aade26ae5a79a9e1fe2cb1d8513",
"sourceCodeHash": "0x5b3dc434f58afd7667f82b8fdfdbea488441be0bae8bdff15cfc5a42ce670cc1"
"initCodeHash": "0x1f9b323a6e1e55a8089bb4de7b7b82d608bccc07e574d79cc690e117f02d0cda",
"sourceCodeHash": "0xb58db3988e7b31467983b91c402e25b00c74c38d5be92eb14e381979eb996dbd"
},
"src/L1/L2OutputOracle.sol": {
"initCodeHash": "0x0e0573841e43e4c5f0df5839db2bdf387f29fed7c830f05960542e7d7109ed4a",
......@@ -88,12 +88,12 @@
"sourceCodeHash": "0xc7258cb394333527bfc58d0a8ba6bd9d90b46b60ace20a500d94192fea60aef4"
},
"src/L2/L2StandardBridge.sol": {
"initCodeHash": "0x7d2089948a373c62cdae80f329d6882eea450f2048f5ad45dbcceaaf37685d80",
"sourceCodeHash": "0xd64cf85ff5ecc1bf368d16532a9e29ba2dfc0f5456bbd3f9f05212c9120a2ed1"
"initCodeHash": "0x85d7cc69dfe340ffeee00d5a0524a199c11078504aa8007903c86572bd34a5c9",
"sourceCodeHash": "0x411d8cf2f9ef44949962aaed71c6b40eb4bb93768888632fa8330bf249c2301b"
},
"src/L2/L2StandardBridgeInterop.sol": {
"initCodeHash": "0x024711e1689bedcdb1e9de8b1c4a440a911634a0ce0a384246b4f9cd683a23f3",
"sourceCodeHash": "0xb92682bb93a87c22e6a2506b64ff609b76376a7d09f514125173c6792c354fc4"
"initCodeHash": "0x46e2d315b8e880f20a5c0ab5579542e6c68461e8f5202a5a5bf8c765fd8b629f",
"sourceCodeHash": "0x97fdf7168d578dc489deb6f4098de765d1019f4be6b6aaa176457947f7bc8397"
},
"src/L2/L2ToL1MessagePasser.sol": {
"initCodeHash": "0xf9d82084dcef31a3737a76d8ee4e5842ea190d0f77ed4678adb3bbb95217050f",
......@@ -192,12 +192,12 @@
"sourceCodeHash": "0x918965e52bbd358ac827ebe35998f5d8fa5ca77d8eb9ab8986b44181b9aaa48a"
},
"src/universal/OptimismMintableERC20.sol": {
"initCodeHash": "0x51346d105fb0ebeb8733add0d53048b5d3d6f2d762c6bb446616c7f5da5eb026",
"sourceCodeHash": "0x876c716f9159909890eef3ffd3348a7f329af07e2899ae5ddc4a7809a3b753ce"
"initCodeHash": "0xc3289416829b252c830ad7d389a430986a7404df4fe0be37cb19e1c40907f047",
"sourceCodeHash": "0xf5e29dd5c750ea935c7281ec916ba5277f5610a0a9e984e53ae5d5245b3cf2f4"
},
"src/universal/OptimismMintableERC20Factory.sol": {
"initCodeHash": "0x080b30bbf556e8782dd2b355d5c9889324cf2ed1f9e6aca22a2e4dc42fab8ce7",
"sourceCodeHash": "0x47158ca0a9278bf367c4eebdb184aa31332f3b5a504f5147cf1c14777d9106ec"
"initCodeHash": "0xb90f9fa00ba07ade844594d0d7fa6b82458f934eb808a0538e6ff1b15a640c42",
"sourceCodeHash": "0x1a90221ddd0cfea197a29a3d66464c547b0ced9cffc92092c60698c89e68149c"
},
"src/universal/OptimismMintableERC721.sol": {
"initCodeHash": "0xa43e7ffce142c0f2ae6ebe22decdf146dd39246830bec5cbd7903b32c2599048",
......
......@@ -75,8 +75,8 @@ contract L1StandardBridge is StandardBridge, ISemver {
);
/// @notice Semantic version.
/// @custom:semver 2.2.1-beta.3
string public constant version = "2.2.1-beta.3";
/// @custom:semver 2.2.1-beta.4
string public constant version = "2.2.1-beta.4";
/// @notice Address of the SuperchainConfig contract.
ISuperchainConfig public superchainConfig;
......
......@@ -58,9 +58,9 @@ contract L2StandardBridge is StandardBridge, ISemver {
);
/// @notice Semantic version.
/// @custom:semver 1.11.1-beta.5
/// @custom:semver 1.11.1-beta.6
function version() public pure virtual returns (string memory) {
return "1.11.1-beta.5";
return "1.11.1-beta.6";
}
/// @notice Constructs the L2StandardBridge contract.
......
......@@ -40,9 +40,9 @@ contract L2StandardBridgeInterop is L2StandardBridge {
event Converted(address indexed from, address indexed to, address indexed caller, uint256 amount);
/// @notice Semantic version.
/// @custom:semver +interop-beta.4
/// @custom:semver +interop-beta.5
function version() public pure override returns (string memory) {
return string.concat(super.version(), "+interop-beta.4");
return string.concat(super.version(), "+interop-beta.5");
}
/// @notice Converts `amount` of `from` token to `to` token.
......
......@@ -12,7 +12,7 @@ import { Preinstalls } from "src/libraries/Preinstalls.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import { ISemver } from "interfaces/universal/ISemver.sol";
import { IOptimismMintableERC20 } from "interfaces/universal/IOptimismMintableERC20.sol";
import { ILegacyMintableERC20 } from "interfaces/universal/ILegacyMintableERC20.sol";
import { ILegacyMintableERC20 } from "interfaces/legacy/ILegacyMintableERC20.sol";
/// @title OptimismMintableERC20
/// @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed
......@@ -47,8 +47,8 @@ contract OptimismMintableERC20 is ERC20Permit, ISemver {
}
/// @notice Semantic version.
/// @custom:semver 1.4.0-beta.4
string public constant version = "1.4.0-beta.4";
/// @custom:semver 1.4.0-beta.5
string public constant version = "1.4.0-beta.5";
/// @notice Getter function for the permit2 address. It deterministically deployed
/// so it will always be at the same address. It is also included as a preinstall,
......
......@@ -51,8 +51,8 @@ contract OptimismMintableERC20Factory is ISemver, Initializable, IOptimismERC20F
/// the OptimismMintableERC20 token contract since this contract
/// is responsible for deploying OptimismMintableERC20 contracts.
/// @notice Semantic version.
/// @custom:semver 1.10.1-beta.6
string public constant version = "1.10.1-beta.6";
/// @custom:semver 1.10.1-beta.7
string public constant version = "1.10.1-beta.7";
/// @notice Constructs the OptimismMintableERC20Factory contract.
constructor() {
......
......@@ -14,7 +14,7 @@ import { Constants } from "src/libraries/Constants.sol";
// Interfaces
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IOptimismMintableERC20 } from "interfaces/universal/IOptimismMintableERC20.sol";
import { ILegacyMintableERC20 } from "interfaces/universal/ILegacyMintableERC20.sol";
import { ILegacyMintableERC20 } from "interfaces/legacy/ILegacyMintableERC20.sol";
import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenger.sol";
/// @custom:upgradeable
......
......@@ -46,6 +46,12 @@ contract L2StandardBridge_Test is CommonTest {
assertEq(address(l2StandardBridge.otherBridge()), address(l1StandardBridge));
}
/// @notice Tests that the version function returns a valid string. We avoid testing the
/// specific value of the string as it changes frequently.
function test_version_succeeds() external view {
assert(bytes(l2StandardBridge.version()).length > 0);
}
/// @dev Ensures that the L2StandardBridge is always not paused. The pausability
/// happens on L1 and not L2.
function test_paused_succeeds() external view {
......@@ -413,7 +419,7 @@ contract PreBridgeERC20To is CommonTest {
// so they should share the same setup and expectEmit calls
function _preBridgeERC20To(bool _isLegacy, address _l2Token) internal {
deal(_l2Token, alice, 100, true);
assertEq(ERC20(L2Token).balanceOf(alice), 100);
assertEq(L2Token.balanceOf(alice), 100);
uint256 nonce = l2CrossDomainMessenger.messageNonce();
bytes memory message =
abi.encodeCall(IStandardBridge.finalizeBridgeERC20, (address(L1Token), _l2Token, alice, bob, 100, hex""));
......
......@@ -50,6 +50,15 @@ contract L2StandardBridgeInterop_Test is CommonTest {
}
}
/// @notice Test suite for getter functions.
contract L2StandardBridgeInterop_Getters_Test is L2StandardBridgeInterop_Test {
/// @notice Tests that the version function returns a valid string. We avoid testing the
/// specific value of the string as it changes frequently.
function test_version_succeeds() external view {
assert(bytes(l2StandardBridge.version()).length > 0);
}
}
/// @notice Test suite when converting from a legacy token to a OptimismSuperchainERC20 token
contract L2StandardBridgeInterop_LegacyToSuper_Test is L2StandardBridgeInterop_Test {
/// @notice Set up the test for converting from a legacy token to a OptimismSuperchainERC20 token
......
......@@ -5,7 +5,7 @@ pragma solidity 0.8.15;
import { CommonTest } from "test/setup/CommonTest.sol";
import { LegacyMintableERC20 } from "src/legacy/LegacyMintableERC20.sol";
import { ILegacyMintableERC20 } from "interfaces/universal/ILegacyMintableERC20.sol";
import { ILegacyMintableERC20 } from "interfaces/legacy/ILegacyMintableERC20.sol";
contract LegacyMintableERC20_Test is CommonTest {
LegacyMintableERC20 legacyMintableERC20;
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
pragma solidity ^0.8.0;
// Forge
import { Test } from "forge-std/Test.sol";
// Testing
import { Setup } from "test/setup/Setup.sol";
import { Events } from "test/setup/Events.sol";
import { FFIInterface } from "test/setup/FFIInterface.sol";
import { Constants } from "src/libraries/Constants.sol";
// Scripts
import { DeployUtils } from "scripts/libraries/DeployUtils.sol";
// Contracts
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol";
import { LegacyMintableERC20 } from "src/legacy/LegacyMintableERC20.sol";
// Libraries
import { Constants } from "src/libraries/Constants.sol";
// Interfaces
import { IOptimismMintableERC20Full } from "interfaces/universal/IOptimismMintableERC20Full.sol";
import { ILegacyMintableERC20Full } from "interfaces/legacy/ILegacyMintableERC20Full.sol";
/// @title CommonTest
/// @dev An extenstion to `Test` that sets up the optimism smart contracts.
......@@ -27,11 +39,11 @@ contract CommonTest is Test, Setup, Events {
ERC20 L1Token;
ERC20 BadL1Token;
OptimismMintableERC20 L2Token;
LegacyMintableERC20 LegacyL2Token;
IOptimismMintableERC20Full L2Token;
ILegacyMintableERC20Full LegacyL2Token;
ERC20 NativeL2Token;
ERC20 BadL2Token;
OptimismMintableERC20 RemoteL1Token;
IOptimismMintableERC20Full RemoteL1Token;
function setUp() public virtual override {
alice = makeAddr("alice");
......@@ -83,16 +95,26 @@ contract CommonTest is Test, Setup, Events {
function bridgeInitializerSetUp() public {
L1Token = new ERC20("Native L1 Token", "L1T");
LegacyL2Token = new LegacyMintableERC20({
_l2Bridge: address(l2StandardBridge),
_l1Token: address(L1Token),
_name: string.concat("LegacyL2-", L1Token.name()),
_symbol: string.concat("LegacyL2-", L1Token.symbol())
});
LegacyL2Token = ILegacyMintableERC20Full(
DeployUtils.create1({
_name: "LegacyMintableERC20",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
ILegacyMintableERC20Full.__constructor__,
(
address(l2StandardBridge),
address(L1Token),
string.concat("LegacyL2-", L1Token.name()),
string.concat("LegacyL2-", L1Token.symbol())
)
)
)
})
);
vm.label(address(LegacyL2Token), "LegacyMintableERC20");
// Deploy the L2 ERC20 now
L2Token = OptimismMintableERC20(
L2Token = IOptimismMintableERC20Full(
l2OptimismMintableERC20Factory.createStandardL2Token(
address(L1Token),
string(abi.encodePacked("L2-", L1Token.name())),
......@@ -100,7 +122,7 @@ contract CommonTest is Test, Setup, Events {
)
);
BadL2Token = OptimismMintableERC20(
BadL2Token = ERC20(
l2OptimismMintableERC20Factory.createStandardL2Token(
address(1),
string(abi.encodePacked("L2-", L1Token.name())),
......@@ -110,7 +132,7 @@ contract CommonTest is Test, Setup, Events {
NativeL2Token = new ERC20("Native L2 Token", "L2T");
RemoteL1Token = OptimismMintableERC20(
RemoteL1Token = IOptimismMintableERC20Full(
l1OptimismMintableERC20Factory.createStandardL2Token(
address(NativeL2Token),
string(abi.encodePacked("L1-", NativeL2Token.name())),
......@@ -118,7 +140,7 @@ contract CommonTest is Test, Setup, Events {
)
);
BadL1Token = OptimismMintableERC20(
BadL1Token = ERC20(
l1OptimismMintableERC20Factory.createStandardL2Token(
address(1),
string(abi.encodePacked("L1-", NativeL2Token.name())),
......
......@@ -3,7 +3,7 @@ pragma solidity 0.8.15;
import { CommonTest } from "test/setup/CommonTest.sol";
import { IOptimismMintableERC20 } from "interfaces/universal/IOptimismMintableERC20.sol";
import { ILegacyMintableERC20 } from "interfaces/universal/ILegacyMintableERC20.sol";
import { ILegacyMintableERC20 } from "interfaces/legacy/ILegacyMintableERC20.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
contract OptimismMintableERC20_Test is CommonTest {
......
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