Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: support permit2 on optimism superchain erc20 and upgrade solady's erc20 implementation #97

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
ae024a5
feat: add superchain erc20 bridge (#61)
agusduha Sep 25, 2024
2a22161
refactor: optimism superchain erc20 redesign (#62)
0xDiscotech Sep 26, 2024
6aaf905
test: add superchain erc20 bridge tests (#65)
agusduha Sep 27, 2024
11fda67
chore: update missing bridge on natspec (#69)
0xDiscotech Sep 27, 2024
7a69a7e
fix: remove superchain erc20 base (#70)
agusduha Sep 27, 2024
07c9c77
refactor: update isuperchainweth (#71)
0xDiscotech Sep 27, 2024
d9bdad1
feat: rename mint/burn and add SuperchainERC20 (#74)
agusduha Oct 1, 2024
2e507b2
fix: refactor zero check (#76)
agusduha Oct 2, 2024
7fcaf6c
Merge branch 'develop' into fix/redesign-merge-conflicts
agusduha Oct 2, 2024
619f23c
fix: pre pr
agusduha Oct 2, 2024
a16cca5
chore: add new solady version and import it for erc20
0xDiscotech Oct 2, 2024
1981789
Merge pull request #77 from defi-wonderland/fix/redesign-merge-conflicts
agusduha Oct 2, 2024
0938dd8
fix: undo forge std changes
0xDiscotech Oct 3, 2024
62235f7
Merge branch 'sc/superchain-erc20-redesign' into chore/erc20-new-sola…
0xDiscotech Oct 3, 2024
68dc9db
chore: re run pre pr script
0xDiscotech Oct 3, 2024
ae019b8
fix: semver natspec check failure (#79)
agusduha Oct 3, 2024
a5aca61
feat: add crosschain erc20 interface (#80)
agusduha Oct 3, 2024
83757ea
fix: superchain bridge natspec (#83)
agusduha Oct 4, 2024
904a0ce
fix: superchain weth natspec (#84)
agusduha Oct 4, 2024
bd87a99
Merge branch 'sc/superchain-erc20-redesign' into chore/erc20-new-sola…
0xDiscotech Oct 4, 2024
9fb4bc6
Merge branch 'sc-feat/crosschain-erc20' into chore/erc20-new-solady-v…
0xDiscotech Oct 4, 2024
3ebb1d1
fix: stop inheriting superchain interfaces (#85)
agusduha Oct 4, 2024
1b4317e
fix: superchain bridge rename (#86)
agusduha Oct 7, 2024
10038c3
fix: fee vault compiler error (#87)
agusduha Oct 7, 2024
9f49b43
Merge branch 'develop' into fix/crosschain-merge-conflicts
agusduha Oct 8, 2024
ab1e074
fix: remove unused imports
agusduha Oct 8, 2024
a79bf4e
Merge pull request #88 from defi-wonderland/fix/crosschain-merge-conf…
agusduha Oct 8, 2024
905ee60
Merge branch 'sc-feat/crosschain-erc20' into chore/erc20-new-solady-v…
0xDiscotech Oct 9, 2024
bdcd7f1
chore: run pre-pr and update vendor interface
0xDiscotech Oct 9, 2024
af9694e
fix: refactor common errors (#90)
agusduha Oct 9, 2024
70e3570
feat: add permit2 on optimism superchain erc20
0xDiscotech Oct 9, 2024
8aaca99
Merge branch 'sc-feat/crosschain-erc20' into chore/erc20-new-solady-v…
0xDiscotech Oct 9, 2024
1fc614a
feat: add permit2
0xDiscotech Oct 9, 2024
553462d
chore: run pre-pr script
0xDiscotech Oct 9, 2024
6c46f9b
fix: reuse unauthorized error (#92)
agusduha Oct 10, 2024
736adf3
Merge branch 'develop' into fix/superchain-erc20-factory-merge-conflicts
agusduha Oct 11, 2024
061b1ff
fix: superchain erc20 factory conflicts
agusduha Oct 11, 2024
97fb300
Merge pull request #93 from defi-wonderland/fix/superchain-erc20-fact…
agusduha Oct 11, 2024
71389b6
fix: rename crosschain functions (#94)
agusduha Oct 11, 2024
7bc9fd5
Merge branch 'sc-feat/crosschain-erc20' into chore/erc20-new-solady-v…
0xDiscotech Oct 11, 2024
39f5caf
chore: run pre-pr
0xDiscotech Oct 11, 2024
222e10c
Merge branch 'develop' into chore/erc20-new-solady-version
0xDiscotech Oct 15, 2024
c19f54d
chore: run pre-pr
0xDiscotech Oct 15, 2024
de3cc8e
chore: run pre-pr
0xDiscotech Oct 15, 2024
9a96c48
feat: add new tests on optimism superchain erc20
0xDiscotech Oct 15, 2024
b5640fa
fix: vars and params naming on newly added tests
0xDiscotech Oct 15, 2024
20f0bc6
fix: var name
0xDiscotech Oct 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@
[submodule "packages/contracts-bedrock/lib/openzeppelin-contracts-v5"]
path = packages/contracts-bedrock/lib/openzeppelin-contracts-v5
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "packages/contracts-bedrock/lib/solady-v0.0.245"]
path = packages/contracts-bedrock/lib/solady-v0.0.245
url = https://github.com/vectorized/solady
1 change: 1 addition & 0 deletions packages/contracts-bedrock/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ remappings = [
'@rari-capital/solmate/=lib/solmate',
'@lib-keccak/=lib/lib-keccak/contracts/lib',
'@solady/=lib/solady/src',
'@solady-v0.0.245/=lib/solady-v0.0.245/src',
'forge-std/=lib/forge-std/src',
'ds-test/=lib/forge-std/lib/ds-test/src',
'safe-contracts/=lib/safe-contracts/contracts',
Expand Down
1 change: 1 addition & 0 deletions packages/contracts-bedrock/lib/solady-v0.0.245
Submodule solady-v0.0.245 added at e0ef35
6 changes: 3 additions & 3 deletions packages/contracts-bedrock/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@
"sourceCodeHash": "0xfea53344596d735eff3be945ed1300dc75a6f8b7b2c02c0043af5b0036f5f239"
},
"src/L2/OptimismSuperchainERC20.sol": {
"initCodeHash": "0xd5c84e45746fd741d541a917ddc1cc0c7043c6b21d5c18040d4bc999d6a7b2db",
"sourceCodeHash": "0xf32130f0b46333daba062c50ff6dcfadce1f177ff753bed2374d499ea9c2d98a"
"initCodeHash": "0x4e25579079d73c93f1d494e1976334b77fc4ec181c67f376d8e2613c7b207f52",
"sourceCodeHash": "0xe41cf3b005f1ea007fc1b5f69f630be5f6ef12d6e5e94a50e3160b0ebe0a1613"
},
"src/L2/OptimismSuperchainERC20Beacon.sol": {
"initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7",
Expand All @@ -125,7 +125,7 @@
},
"src/L2/SuperchainERC20.sol": {
"initCodeHash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
"sourceCodeHash": "0x75d061633a141af11a19b86e599a1725dfae8d245dcddfb6bb244a50d5e53f96"
"sourceCodeHash": "0x6a384ccfb6f2f7316c1b33873a1630b5179e52475951d31771656e06d2b11519"
},
"src/L2/SuperchainTokenBridge.sol": {
"initCodeHash": "0x07fc1d495928d9c13bd945a049d17e1d105d01c2082a7719e5d18cbc0e1c7d9e",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,11 @@
"name": "NotInitializing",
"type": "error"
},
{
"inputs": [],
"name": "Permit2AllowanceIsFixedAtInfinity",
"type": "error"
},
{
"inputs": [],
"name": "PermitExpired",
Expand Down
9 changes: 7 additions & 2 deletions packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165 {
}

/// @notice Semantic version.
/// @custom:semver 1.0.0-beta.6
string public constant override version = "1.0.0-beta.6";
/// @custom:semver 1.0.0-beta.7
string public constant override version = "1.0.0-beta.7";

/// @notice Constructs the OptimismSuperchainERC20 contract.
constructor() {
Expand Down Expand Up @@ -141,4 +141,9 @@ contract OptimismSuperchainERC20 is SuperchainERC20, Initializable, ERC165 {
function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) {
return _interfaceId == type(IOptimismSuperchainERC20).interfaceId || super.supportsInterface(_interfaceId);
}

/// @notice Sets Permit2 contract's allowance at infinity.
function _givePermit2InfiniteAllowance() internal view virtual override returns (bool) {
return true;
}
}
6 changes: 3 additions & 3 deletions packages/contracts-bedrock/src/L2/SuperchainERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.25;
import { ICrosschainERC20 } from "src/L2/interfaces/ICrosschainERC20.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { ERC20 } from "@solady/tokens/ERC20.sol";
import { ERC20 } from "@solady-v0.0.245/tokens/ERC20.sol";
import { Unauthorized } from "src/libraries/errors/CommonErrors.sol";

/// @title SuperchainERC20
Expand All @@ -19,9 +19,9 @@ abstract contract SuperchainERC20 is ERC20, ICrosschainERC20, ISemver {
}

/// @notice Semantic version.
/// @custom:semver 1.0.0-beta.1
/// @custom:semver 1.0.0-beta.2
function version() external view virtual returns (string memory) {
return "1.0.0-beta.1";
return "1.0.0-beta.2";
}

/// @notice Allows the SuperchainTokenBridge to mint tokens.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ interface IERC20Solady {
/// @dev The permit has expired.
error PermitExpired();

/// @dev The allowance of Permit2 is fixed at infinity.
error Permit2AllowanceIsFixedAtInfinity();

/// @dev Emitted when `amount` tokens is transferred from `from` to `to`.
event Transfer(address indexed from, address indexed to, uint256 amount);

Expand Down
72 changes: 67 additions & 5 deletions packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";

// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
import { IERC20 } from "@openzeppelin/contracts-v5/token/ERC20/IERC20.sol";
import { IERC20Solady } from "src/vendor/interfaces/IERC20Solady.sol";

import { Initializable } from "@openzeppelin/contracts-v5/proxy/utils/Initializable.sol";
import { IERC165 } from "@openzeppelin/contracts-v5/utils/introspection/IERC165.sol";
import { IBeacon } from "@openzeppelin/contracts-v5/proxy/beacon/IBeacon.sol";
import { BeaconProxy } from "@openzeppelin/contracts-v5/proxy/beacon/BeaconProxy.sol";
import { Unauthorized } from "src/libraries/errors/CommonErrors.sol";
import { Preinstalls } from "src/libraries/Preinstalls.sol";

// Target contract
import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol";
Expand Down Expand Up @@ -142,12 +144,12 @@ contract OptimismSuperchainERC20Test is Test {
vm.assume(_to != ZERO_ADDRESS);

// Get the total supply and balance of `_to` before the mint to compare later on the assertions
uint256 _totalSupplyBefore = IERC20(address(optimismSuperchainERC20)).totalSupply();
uint256 _toBalanceBefore = IERC20(address(optimismSuperchainERC20)).balanceOf(_to);
uint256 _totalSupplyBefore = IERC20Solady(address(optimismSuperchainERC20)).totalSupply();
uint256 _toBalanceBefore = IERC20Solady(address(optimismSuperchainERC20)).balanceOf(_to);

// Look for the emit of the `Transfer` event
vm.expectEmit(address(optimismSuperchainERC20));
emit IERC20.Transfer(ZERO_ADDRESS, _to, _amount);
emit IERC20Solady.Transfer(ZERO_ADDRESS, _to, _amount);

// Look for the emit of the `Mint` event
vm.expectEmit(address(optimismSuperchainERC20));
Expand Down Expand Up @@ -200,7 +202,7 @@ contract OptimismSuperchainERC20Test is Test {

// Look for the emit of the `Transfer` event
vm.expectEmit(address(optimismSuperchainERC20));
emit IERC20.Transfer(_from, ZERO_ADDRESS, _amount);
emit IERC20Solady.Transfer(_from, ZERO_ADDRESS, _amount);

// Look for the emit of the `Burn` event
vm.expectEmit(address(optimismSuperchainERC20));
Expand Down Expand Up @@ -252,4 +254,64 @@ contract OptimismSuperchainERC20Test is Test {
vm.assume(_interfaceId != type(IOptimismSuperchainERC20).interfaceId);
assertFalse(optimismSuperchainERC20.supportsInterface(_interfaceId));
}

/// @notice Tests that the allowance function returns the max uint256 value when the spender is Permit.
/// @param _randomCaller The address that will call the function - used to fuzz better since the behaviour should be
/// the same regardless of the caller.
/// @param _owner The funds owner.
function testFuzz_allowance_fromPermit2_succeeds(address _randomCaller, address _owner) public {
vm.prank(_randomCaller);
uint256 _allowance = optimismSuperchainERC20.allowance(_owner, Preinstalls.Permit2);

assertEq(_allowance, type(uint256).max);
}

/// @notice Tests that the allowance function returns the correct allowance when the spender is not Permit.
/// @param _randomCaller The address that will call the function - used to fuzz better
/// since the behaviour should be the same regardless of the caller.
/// @param _owner The funds owner.
/// @param _guy The address of the spender - It cannot be Permit2.
function testFuzz_allowance_succeeds(address _randomCaller, address _owner, address _guy, uint256 _amount) public {
// Assume
vm.assume(_guy != Preinstalls.Permit2);

// Arrange
vm.prank(_owner);
optimismSuperchainERC20.approve(_guy, _amount);

// Act
vm.prank(_randomCaller);
uint256 _allowance = optimismSuperchainERC20.allowance(_owner, _guy);

// Assert
assertEq(_allowance, _amount);
}

/// @notice Tests that `transferFrom` works when the caller (spender) is Permit2, without any explicit approval.
/// @param _owner The funds owner.
/// @param _recipient The address of the recipient.
/// @param _amount The amount of tokens to transfer.
function testFuzz_transferFrom_whenPermit2IsCaller_succeeds(
address _owner,
address _recipient,
uint256 _amount
)
public
{
// Arrange
deal(address(optimismSuperchainERC20), _owner, _amount);

vm.expectEmit(address(optimismSuperchainERC20));
emit IERC20Solady.Transfer(_owner, _recipient, _amount);

// Act
vm.prank(Preinstalls.Permit2);
optimismSuperchainERC20.transferFrom(_owner, _recipient, _amount);

// Assert
assertEq(optimismSuperchainERC20.balanceOf(_recipient), _amount);
// Handle the case where the source and destination are the same to check the source balance.
if (_owner != _recipient) assertEq(optimismSuperchainERC20.balanceOf(_owner), 0);
else assertEq(optimismSuperchainERC20.balanceOf(_owner), _amount);
}
}
6 changes: 3 additions & 3 deletions packages/contracts-bedrock/test/L2/SuperchainERC20.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Test } from "forge-std/Test.sol";

// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
import { IERC20 } from "@openzeppelin/contracts-v5/token/ERC20/IERC20.sol";
import { IERC20Solady } from "src/vendor/interfaces/IERC20Solady.sol";

// Target contract
import { SuperchainERC20 } from "src/L2/SuperchainERC20.sol";
Expand Down Expand Up @@ -58,7 +58,7 @@ contract SuperchainERC20Test is Test {

// Look for the emit of the `Transfer` event
vm.expectEmit(address(superchainERC20));
emit IERC20.Transfer(ZERO_ADDRESS, _to, _amount);
emit IERC20Solady.Transfer(ZERO_ADDRESS, _to, _amount);

// Look for the emit of the `CrosschainMinted` event
vm.expectEmit(address(superchainERC20));
Expand Down Expand Up @@ -101,7 +101,7 @@ contract SuperchainERC20Test is Test {

// Look for the emit of the `Transfer` event
vm.expectEmit(address(superchainERC20));
emit IERC20.Transfer(_from, ZERO_ADDRESS, _amount);
emit IERC20Solady.Transfer(_from, ZERO_ADDRESS, _amount);

// Look for the emit of the `CrosschainBurnt` event
vm.expectEmit(address(superchainERC20));
Expand Down