-
Notifications
You must be signed in to change notification settings - Fork 358
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'sync-layer-stable' into sb-use-l2-chain-admin
- Loading branch information
Showing
4 changed files
with
196 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ import {GatewayUpgradeFailed} from "./ZkSyncUpgradeErrors.sol"; | |
|
||
import {IGatewayUpgrade} from "./IGatewayUpgrade.sol"; | ||
import {IL2ContractDeployer} from "../common/interfaces/IL2ContractDeployer.sol"; | ||
import {L1GatewayHelper} from "./L1GatewayHelper.sol"; | ||
import {L1GatewayBase} from "./L1GatewayBase.sol"; | ||
|
||
// solhint-disable-next-line gas-struct-packing | ||
struct GatewayUpgradeEncodedInput { | ||
|
@@ -29,7 +29,7 @@ struct GatewayUpgradeEncodedInput { | |
/// @author Matter Labs | ||
/// @custom:security-contact [email protected] | ||
/// @notice This upgrade will be used to migrate Era to be part of the ZK chain ecosystem contracts. | ||
contract GatewayUpgrade is BaseZkSyncUpgrade { | ||
contract GatewayUpgrade is BaseZkSyncUpgrade, L1GatewayBase { | ||
using PriorityQueue for PriorityQueue.Queue; | ||
using PriorityTree for PriorityTree.Tree; | ||
|
||
|
@@ -61,11 +61,7 @@ contract GatewayUpgrade is BaseZkSyncUpgrade { | |
bytes memory gatewayUpgradeCalldata = abi.encode( | ||
encodedInput.ctmDeployer, | ||
encodedInput.fixedForceDeploymentsData, | ||
L1GatewayHelper.getZKChainSpecificForceDeploymentsData( | ||
s, | ||
encodedInput.wrappedBaseTokenStore, | ||
s.__DEPRECATED_baseToken | ||
) | ||
getZKChainSpecificForceDeploymentsData(s, encodedInput.wrappedBaseTokenStore, s.__DEPRECATED_baseToken) | ||
); | ||
encodedInput.forceDeployments[encodedInput.l2GatewayUpgradePosition].input = gatewayUpgradeCalldata; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,10 +12,10 @@ import {ZKChainStorage} from "../state-transition/chain-deps/ZKChainStorage.sol" | |
import {L2WrappedBaseTokenStore} from "../bridge/L2WrappedBaseTokenStore.sol"; | ||
import {IERC20Metadata} from "@openzeppelin/contracts-v4/token/ERC20/extensions/IERC20Metadata.sol"; | ||
|
||
/// @title L1GatewayHelper | ||
/// @title L1GatewayBase | ||
/// @author Matter Labs | ||
/// @custom:security-contact [email protected] | ||
library L1GatewayHelper { | ||
abstract contract L1GatewayBase { | ||
/// @notice The function to retrieve the chain-specific upgrade data. | ||
/// @param s The pointer to the storage of the chain. | ||
/// @param _wrappedBaseTokenStore The address of the `L2WrappedBaseTokenStore` contract. | ||
|
@@ -43,8 +43,18 @@ library L1GatewayHelper { | |
baseTokenName = string("Ether"); | ||
baseTokenSymbol = string("ETH"); | ||
} else { | ||
baseTokenName = IERC20Metadata(_baseTokenAddress).name(); | ||
baseTokenSymbol = IERC20Metadata(_baseTokenAddress).symbol(); | ||
try this.getTokenName(_baseTokenAddress) returns (string memory name) { | ||
baseTokenName = name; | ||
} catch { | ||
baseTokenName = string("Base Token"); | ||
} | ||
|
||
try this.getTokenSymbol(_baseTokenAddress) returns (string memory symbol) { | ||
baseTokenSymbol = symbol; | ||
} catch { | ||
// "BT" is an acronym for "Base Token" | ||
baseTokenSymbol = string("BT"); | ||
} | ||
} | ||
|
||
ZKChainSpecificForceDeploymentsData | ||
|
@@ -58,4 +68,12 @@ library L1GatewayHelper { | |
}); | ||
return abi.encode(additionalForceDeploymentsData); | ||
} | ||
|
||
function getTokenName(address _token) external view returns (string memory) { | ||
return IERC20Metadata(_token).name(); | ||
} | ||
|
||
function getTokenSymbol(address _token) external view returns (string memory) { | ||
return IERC20Metadata(_token).symbol(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,11 +19,11 @@ import {IBridgehub} from "../bridgehub/IBridgehub.sol"; | |
|
||
import {VerifierParams} from "../state-transition/chain-interfaces/IVerifier.sol"; | ||
import {L2ContractHelper} from "../common/libraries/L2ContractHelper.sol"; | ||
import {L1GatewayHelper} from "./L1GatewayHelper.sol"; | ||
import {L1GatewayBase} from "./L1GatewayBase.sol"; | ||
|
||
/// @author Matter Labs | ||
/// @custom:security-contact [email protected] | ||
contract L1GenesisUpgrade is IL1GenesisUpgrade, BaseZkSyncUpgradeGenesis { | ||
contract L1GenesisUpgrade is IL1GenesisUpgrade, BaseZkSyncUpgradeGenesis, L1GatewayBase { | ||
/// @notice The main function that will be called by the Admin facet. | ||
/// @param _l1GenesisUpgrade the address of the l1 genesis upgrade | ||
/// @param _chainId the chain id | ||
|
@@ -46,7 +46,7 @@ contract L1GenesisUpgrade is IL1GenesisUpgrade, BaseZkSyncUpgradeGenesis { | |
{ | ||
bytes memory complexUpgraderCalldata; | ||
{ | ||
bytes memory additionalForceDeploymentsData = L1GatewayHelper.getZKChainSpecificForceDeploymentsData( | ||
bytes memory additionalForceDeploymentsData = getZKChainSpecificForceDeploymentsData( | ||
s, | ||
address(0), | ||
baseTokenAddress | ||
|
168 changes: 168 additions & 0 deletions
168
l1-contracts/test/foundry/l1/unit/concrete/upgrades/L1GatewayBase.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.24; | ||
|
||
import "forge-std/Test.sol"; | ||
import {L1GatewayBase} from "contracts/upgrades/L1GatewayBase.sol"; // Adjust the import path accordingly | ||
import {ZKChainStorage} from "contracts/state-transition/chain-deps/ZKChainStorage.sol"; | ||
import {IBridgehub} from "contracts/bridgehub/IBridgehub.sol"; | ||
import {IL1SharedBridgeLegacy} from "contracts/bridge/interfaces/IL1SharedBridgeLegacy.sol"; | ||
import {ETH_TOKEN_ADDRESS} from "contracts/common/Config.sol"; | ||
import {ZKChainSpecificForceDeploymentsData} from "contracts/state-transition/l2-deps/IL2GenesisUpgrade.sol"; | ||
|
||
// Concrete implementation of L1GatewayBase for testing | ||
contract TestL1GatewayBase is L1GatewayBase { | ||
ZKChainStorage s; | ||
|
||
// For testing, we need to be able to call the internal function from outside | ||
function requestGetZKChainSpecificForceDeploymentsData( | ||
address _wrappedBaseTokenStore, | ||
address _baseTokenAddress | ||
) external view returns (bytes memory) { | ||
return getZKChainSpecificForceDeploymentsData(s, _wrappedBaseTokenStore, _baseTokenAddress); | ||
} | ||
|
||
function setChainId(uint256 _chainId) external { | ||
s.chainId = _chainId; | ||
} | ||
|
||
function setBaseTokenAssetId(bytes32 _assetId) external { | ||
s.baseTokenAssetId = _assetId; | ||
} | ||
|
||
function setBrideghub(address _bridgehub) external { | ||
s.bridgehub = _bridgehub; | ||
} | ||
} | ||
|
||
contract MockERC20TokenWithMetadata { | ||
string private _name; | ||
string private _symbol; | ||
|
||
constructor(string memory name_, string memory symbol_) { | ||
_name = name_; | ||
_symbol = symbol_; | ||
} | ||
|
||
function name() external view returns (string memory) { | ||
return _name; | ||
} | ||
|
||
function symbol() external view returns (string memory) { | ||
return _symbol; | ||
} | ||
} | ||
|
||
contract MockERC20TokenWithoutMetadata {} | ||
|
||
contract L1GatewayBaseTest is Test { | ||
TestL1GatewayBase testGateway; | ||
// Mocks for dependencies | ||
address bridgehubMock; | ||
address sharedBridgeMock; | ||
// MockL2WrappedBaseTokenStore wrappedBaseTokenStoreMock; | ||
|
||
// Addresses | ||
address sharedBridgeAddress; | ||
address legacySharedBridgeAddress; | ||
|
||
// Chain ID for testing | ||
uint256 chainId = 123; | ||
bytes32 baseTokenAssetId; | ||
|
||
function setUp() public { | ||
baseTokenAssetId = bytes32("baseTokenAssetId"); | ||
bridgehubMock = makeAddr("bridgehubMock"); | ||
sharedBridgeMock = makeAddr("sharedBridgeMock"); | ||
legacySharedBridgeAddress = makeAddr("legacySharedBridgeAddress"); | ||
|
||
testGateway = new TestL1GatewayBase(); | ||
|
||
// Initialize ZKChainStorage | ||
testGateway.setChainId(chainId); | ||
testGateway.setBrideghub(bridgehubMock); | ||
// Set base token asset ID | ||
testGateway.setBaseTokenAssetId(baseTokenAssetId); | ||
|
||
vm.mockCall(bridgehubMock, abi.encodeCall(IBridgehub.sharedBridge, ()), abi.encode(sharedBridgeMock)); | ||
vm.mockCall( | ||
sharedBridgeMock, | ||
abi.encodeCall(IL1SharedBridgeLegacy.l2BridgeAddress, (chainId)), | ||
abi.encode(address(legacySharedBridgeAddress)) | ||
); | ||
} | ||
|
||
// Test with ETH as the base token | ||
function testWithETH() public { | ||
// No wrapped base token store | ||
address _wrappedBaseTokenStore = address(0); | ||
|
||
// Call the function | ||
bytes memory data = testGateway.requestGetZKChainSpecificForceDeploymentsData( | ||
_wrappedBaseTokenStore, | ||
ETH_TOKEN_ADDRESS | ||
); | ||
|
||
// Decode the returned data | ||
ZKChainSpecificForceDeploymentsData memory chainData = abi.decode(data, (ZKChainSpecificForceDeploymentsData)); | ||
|
||
// Check the values | ||
assertEq(chainData.baseTokenAssetId, baseTokenAssetId); | ||
assertEq(chainData.l2LegacySharedBridge, legacySharedBridgeAddress); | ||
assertEq(chainData.predeployedL2WethAddress, address(0)); | ||
assertEq(chainData.baseTokenL1Address, ETH_TOKEN_ADDRESS); | ||
assertEq(chainData.baseTokenName, "Ether"); | ||
assertEq(chainData.baseTokenSymbol, "ETH"); | ||
} | ||
|
||
// Test with ERC20 that correctly implements metadata | ||
function testWithERC20TokenWithMetadata() public { | ||
// Deploy a mock ERC20 token that implements name() and symbol() | ||
MockERC20TokenWithMetadata token = new MockERC20TokenWithMetadata("Test Token", "TTK"); | ||
|
||
// No wrapped base token store | ||
address _wrappedBaseTokenStore = address(0); | ||
|
||
// Call the function | ||
bytes memory data = testGateway.requestGetZKChainSpecificForceDeploymentsData( | ||
_wrappedBaseTokenStore, | ||
address(token) | ||
); | ||
|
||
// Decode the returned data | ||
ZKChainSpecificForceDeploymentsData memory chainData = abi.decode(data, (ZKChainSpecificForceDeploymentsData)); | ||
|
||
// Check the values | ||
assertEq(chainData.baseTokenAssetId, baseTokenAssetId); | ||
assertEq(chainData.l2LegacySharedBridge, legacySharedBridgeAddress); | ||
assertEq(chainData.predeployedL2WethAddress, address(0)); | ||
assertEq(chainData.baseTokenL1Address, address(token)); | ||
assertEq(chainData.baseTokenName, "Test Token"); | ||
assertEq(chainData.baseTokenSymbol, "TTK"); | ||
} | ||
|
||
// Test with ERC20 that does not implement metadata | ||
function testWithERC20TokenWithoutMetadata() public { | ||
// Deploy a mock ERC20 token that does not implement name() and symbol() | ||
MockERC20TokenWithoutMetadata token = new MockERC20TokenWithoutMetadata(); | ||
|
||
// No wrapped base token store | ||
address _wrappedBaseTokenStore = address(0); | ||
|
||
// Call the function | ||
bytes memory data = testGateway.requestGetZKChainSpecificForceDeploymentsData( | ||
_wrappedBaseTokenStore, | ||
address(token) | ||
); | ||
|
||
// Decode the returned data | ||
ZKChainSpecificForceDeploymentsData memory chainData = abi.decode(data, (ZKChainSpecificForceDeploymentsData)); | ||
|
||
// Check the values | ||
assertEq(chainData.baseTokenAssetId, baseTokenAssetId); | ||
assertEq(chainData.l2LegacySharedBridge, legacySharedBridgeAddress); | ||
assertEq(chainData.predeployedL2WethAddress, address(0)); | ||
assertEq(chainData.baseTokenL1Address, address(token)); | ||
assertEq(chainData.baseTokenName, "Base Token"); | ||
assertEq(chainData.baseTokenSymbol, "BT"); | ||
} | ||
} |