From f5a359ba7a009b2fb982fc3b0ae5bea6e173532d Mon Sep 17 00:00:00 2001 From: Ignasi Date: Thu, 12 Sep 2024 10:35:31 +0200 Subject: [PATCH 1/8] Bridge implementation for sovereign chains + tests Add more testing Refactor function overrite Refactor GlobalExitRoot contracts for dovereign chains First testing iteration sovereign chains Review fixes Review fixes II Review fixes III Full testing coverage for sovereign contracts Added sovereign bridge features - Batch call function implementation to remap multiple tokens - Allow migrating legacy to updated tokens natively - Added weth mapped address are initializer Refactor migrateLegacyToken function Coverage tests + fix 1_genesis script + typos Fix sovereign chain deployment at docker and removed struct Add remove ger function at sovereign GER contracts Review comment and add override at initialize function Refactor gerManagerSovereigns Create batch for pessimistic networks --- contracts/PolygonZkEVMGlobalExitRootL2.sol | 6 + .../IBasePolygonZkEVMGlobalExitRoot.sol | 20 + contracts/v2/PolygonZkEVMBridgeV2.sol | 58 +- contracts/v2/PolygonZkEVMGlobalExitRootV2.sol | 2 +- .../interfaces/IBridgeL2SovereignChains.sol | 60 + .../BridgeL2SovereignChain.sol | 414 ++++ .../GlobalExitRootManagerL2SovereignChain.sol | 108 + deployment/v2/1_createGenesis.ts | 49 +- deployment/v2/4_createRollup.ts | 88 +- deployment/v2/README.md | 28 +- deployment/v2/deploy_parameters.json.example | 3 +- hardhat.config.ts | 10 + package.json | 2 +- ...dgeL2GasTokenMappedSovereignChains.test.ts | 1590 ++++++++++++ .../BridgeL2GasTokensSovereignChains.test.ts | 1603 ++++++++++++ .../BridgeL2SovereignChain.test.ts | 2201 +++++++++++++++++ 16 files changed, 6167 insertions(+), 75 deletions(-) create mode 100644 contracts/v2/interfaces/IBridgeL2SovereignChains.sol create mode 100644 contracts/v2/sovereignChains/BridgeL2SovereignChain.sol create mode 100644 contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol create mode 100644 test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts create mode 100644 test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts create mode 100644 test/contractsv2/BridgeL2SovereignChain.test.ts diff --git a/contracts/PolygonZkEVMGlobalExitRootL2.sol b/contracts/PolygonZkEVMGlobalExitRootL2.sol index 1a7bbe33c..13d0603d9 100644 --- a/contracts/PolygonZkEVMGlobalExitRootL2.sol +++ b/contracts/PolygonZkEVMGlobalExitRootL2.sol @@ -27,6 +27,12 @@ contract PolygonZkEVMGlobalExitRootL2 is IBasePolygonZkEVMGlobalExitRoot { // PolygonZkEVM Bridge address address public immutable bridgeAddress; + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + */ + uint256[50] private _gap; + /** * @param _bridgeAddress PolygonZkEVMBridge contract address */ diff --git a/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol b/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol index 3d558f9b0..383b58ff0 100644 --- a/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol +++ b/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol @@ -8,6 +8,26 @@ interface IBasePolygonZkEVMGlobalExitRoot { */ error OnlyAllowedContracts(); + /** + * @dev Thrown when the caller is not the coinbase + */ + error OnlyAggOracleOrCoinbase(); + + /** + * @dev Thrown when trying to insert a global exit root that is already set + */ + error GlobalExitRootAlreadySet(); + + /** + * @dev Thrown when trying to remove more global exit roots thank inserted + */ + error NotEnoughGlobalExitRootsInserted(); + + /** + * @dev Thrown when trying to remove a ger that is not the last one + */ + error NotLastInsertedGlobalExitRoot(); + function updateExitRoot(bytes32 newRollupExitRoot) external; function globalExitRootMap( diff --git a/contracts/v2/PolygonZkEVMBridgeV2.sol b/contracts/v2/PolygonZkEVMBridgeV2.sol index 8f88fa8e5..4b8eea592 100644 --- a/contracts/v2/PolygonZkEVMBridgeV2.sol +++ b/contracts/v2/PolygonZkEVMBridgeV2.sol @@ -91,6 +91,12 @@ contract PolygonZkEVMBridgeV2 is // WETH address TokenWrapped public WETHToken; + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + */ + uint256[50] private _gap; + /** * @dev Emitted when bridge assets or messages to another network */ @@ -238,7 +244,7 @@ contract PolygonZkEVMBridgeV2 is // In case ether is the native token, WETHToken will be 0, and the address 0 is already checked if (token == address(WETHToken)) { // Burn tokens - TokenWrapped(token).burn(msg.sender, amount); + _bridgeWrappedAsset(TokenWrapped(token), amount); // Both origin network and originTokenAddress will be 0 // Metadata will be empty @@ -250,8 +256,7 @@ contract PolygonZkEVMBridgeV2 is if (tokenInfo.originTokenAddress != address(0)) { // The token is a wrapped token from another network - // Burn tokens - TokenWrapped(token).burn(msg.sender, amount); + _bridgeWrappedAsset(TokenWrapped(token), amount); originTokenAddress = tokenInfo.originTokenAddress; originNetwork = tokenInfo.originNetwork; @@ -364,7 +369,7 @@ contract PolygonZkEVMBridgeV2 is } // Burn wETH tokens - WETHToken.burn(msg.sender, amountWETH); + _bridgeWrappedAsset(WETHToken, amountWETH); _bridgeMessage( destinationNetwork, @@ -492,7 +497,7 @@ contract PolygonZkEVMBridgeV2 is } } else { // Claim wETH - WETHToken.mint(destinationAddress, amount); + _claimWrappedAsset(WETHToken, destinationAddress, amount); } } else { // Check if it's gas token @@ -536,7 +541,11 @@ contract PolygonZkEVMBridgeV2 is ); // Mint tokens for the destination address - newWrappedToken.mint(destinationAddress, amount); + _claimWrappedAsset( + newWrappedToken, + destinationAddress, + amount + ); // Create mappings tokenInfoToWrappedToken[tokenInfoHash] = address( @@ -555,7 +564,8 @@ contract PolygonZkEVMBridgeV2 is ); } else { // Use the existing wrapped erc20 - TokenWrapped(wrappedToken).mint( + _claimWrappedAsset( + TokenWrapped(wrappedToken), destinationAddress, amount ); @@ -608,7 +618,7 @@ contract PolygonZkEVMBridgeV2 is address destinationAddress, uint256 amount, bytes calldata metadata - ) external ifNotEmergencyState { + ) external virtual ifNotEmergencyState { // Destination network must be this networkID if (destinationNetwork != networkID) { revert DestinationNetworkInvalid(); @@ -646,7 +656,7 @@ contract PolygonZkEVMBridgeV2 is ); } else { // Mint wETH tokens - WETHToken.mint(destinationAddress, amount); + _claimWrappedAsset(WETHToken, destinationAddress, amount); // Execute message /* solhint-disable avoid-low-level-calls */ @@ -895,6 +905,36 @@ contract PolygonZkEVMBridgeV2 is globalExitRootManager.updateExitRoot(getRoot()); } + /** + * @notice Burn tokens from wrapped token to execute the bridge + * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + * @param tokenWrapped Wrapped token to burnt + * @param amount Amount of tokens + */ + function _bridgeWrappedAsset( + TokenWrapped tokenWrapped, + uint256 amount + ) internal virtual { + // Burn tokens + tokenWrapped.burn(msg.sender, amount); + } + + /** + * @notice Mints tokens from wrapped token to proceed with the claim + * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + * @param tokenWrapped Wrapped token to mint + * @param destinationAddress Minted token receiver + * @param amount Amount of tokens + */ + function _claimWrappedAsset( + TokenWrapped tokenWrapped, + address destinationAddress, + uint256 amount + ) internal virtual { + // Burn tokens + tokenWrapped.mint(destinationAddress, amount); + } + /** * @notice Function decode an index into a wordPos and bitPos * @param index Index diff --git a/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol b/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol index 24143e6a5..c904686b5 100644 --- a/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol +++ b/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol @@ -78,7 +78,7 @@ contract PolygonZkEVMGlobalExitRootV2 is * @param newRoot new exit tree root */ function updateExitRoot(bytes32 newRoot) external { - // Store storage variables into temporary variables since will be used multiple times + // Store storage variables into temporal variables since will be used multiple times bytes32 cacheLastRollupExitRoot; bytes32 cacheLastMainnetExitRoot; diff --git a/contracts/v2/interfaces/IBridgeL2SovereignChains.sol b/contracts/v2/interfaces/IBridgeL2SovereignChains.sol new file mode 100644 index 000000000..195746aa5 --- /dev/null +++ b/contracts/v2/interfaces/IBridgeL2SovereignChains.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity ^0.8.20; +import "../../interfaces/IBasePolygonZkEVMGlobalExitRoot.sol"; +import "./IPolygonZkEVMBridgeV2.sol"; + +interface IBridgeL2SovereignChains is IPolygonZkEVMBridgeV2 { + /** + * @dev Thrown when try to set a zero address to a non valid zero address field + */ + error InvalidZeroAddress(); + + /** + * @dev Thrown when the origin network is invalid + */ + error OriginNetworkInvalid(); + + /** + * @dev Thrown when sender is not the bridge manager + * @notice Bridge manager can set custom mapping for any token + */ + error OnlyBridgeManager(); + + /** + * @dev Thrown when bridge manager address is invalid + */ + error NotValidBridgeManager(); + + /** + * @dev Thrown when trying to remove a token mapping that has not been updated by a new one + */ + error TokenNotMapped(); + + /** + * @dev Thrown when trying to migrate a legacy token that is already the current token + */ + error TokenAlreadyUpdated(); + + /** + * @dev Thrown when initializing sovereign bridge with invalid sovereign WETH token params + */ + error InvalidSovereignWETHAddressParams(); + + /** + * @dev Thrown when initializing sovereign bridge with invalid sovereign WETH token params + */ + error InvalidInitializeFunction(); + + function initialize( + uint32 _networkID, + address _gasTokenAddress, + uint32 _gasTokenNetwork, + IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager, + address _polygonRollupManager, + bytes memory _gasTokenMetadata, + address _bridgeManager, + address sovereignWETHAddress, + bool _sovereignWETHAddressIsNotMintable + ) external; +} diff --git a/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol b/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol new file mode 100644 index 000000000..686c49366 --- /dev/null +++ b/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity 0.8.20; + +import "../interfaces/IBridgeL2SovereignChains.sol"; +import "../PolygonZkEVMBridgeV2.sol"; + +// WARNING: not audited + +/** + * Sovereign chains bridge that will be deployed on Ethereum and all Sovereign chains + * Contract responsible to manage the token interactions with other networks + */ +contract BridgeL2SovereignChain is + PolygonZkEVMBridgeV2, + IBridgeL2SovereignChains +{ + using SafeERC20Upgradeable for IERC20Upgradeable; + + // Map to store wrappedAddresses that are not mintable + mapping(address wrappedAddress => bool isNotMintable) + public wrappedAddressIsNotMintable; + + // Bridge manager address; can set custom mapping for any token + address public bridgeManager; + + /** + * @dev Emitted when a bridge manager is updated + */ + event SetBridgeManager(address bridgeManager); + + /** + * @dev Emitted when a token address is remapped by a sovereign token address + */ + event SetSovereignTokenAddress( + uint32 originNetwork, + address originTokenAddress, + address sovereignTokenAddress, + bool isNotMintable + ); + + /** + * @dev Emitted when a legacy token is migrated to a new token + */ + event MigrateLegacyToken( + address sender, + address legacyTokenAddress, + address updatedTokenAddress, + uint256 amount + ); + + /** + * @dev Emitted when a remapped token is removed from mapping + */ + event RemoveSovereignTokenAddress(address sovereignTokenAddress); + + /** + * @dev Emitted when a WETH address is remapped by a sovereign WETH address + */ + event SetSovereignWETHAddress( + address sovereignWETHTokenAddress, + bool isNotMintable + ); + + /** + * Disable initializers on the implementation following the best practices + */ + constructor() { + _disableInitializers(); + } + + /** + * @param _networkID networkID + * @param _gasTokenAddress gas token address + * @param _gasTokenNetwork gas token network + * @param _globalExitRootManager global exit root manager address + * @param _polygonRollupManager Rollup manager address + * @notice The value of `_polygonRollupManager` on the L2 deployment of the contract will be address(0), so + * emergency state is not possible for the L2 deployment of the bridge, intentionally + * @param _gasTokenMetadata Abi encoded gas token metadata + * @param _bridgeManager bridge manager address + * @param _sovereignWETHAddress sovereign WETH address + * @param _sovereignWETHAddressIsNotMintable Flag to indicate if the wrapped ETH is not mintable + */ + function initialize( + uint32 _networkID, + address _gasTokenAddress, + uint32 _gasTokenNetwork, + IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager, + address _polygonRollupManager, + bytes memory _gasTokenMetadata, + address _bridgeManager, + address _sovereignWETHAddress, + bool _sovereignWETHAddressIsNotMintable + ) public virtual initializer { + networkID = _networkID; + globalExitRootManager = _globalExitRootManager; + polygonRollupManager = _polygonRollupManager; + bridgeManager = _bridgeManager; + + // Set gas token + if (_gasTokenAddress == address(0)) { + // Gas token will be ether + if (_gasTokenNetwork != 0) { + revert GasTokenNetworkMustBeZeroOnEther(); + } + // Health check for sovereign WETH address + if ( + _sovereignWETHAddress != address(0) || + _sovereignWETHAddressIsNotMintable == true + ) { + revert InvalidSovereignWETHAddressParams(); + } + // WETHToken, gasTokenAddress and gasTokenNetwork will be 0 + // gasTokenMetadata will be empty + } else { + // Gas token will be an erc20 + gasTokenAddress = _gasTokenAddress; + gasTokenNetwork = _gasTokenNetwork; + gasTokenMetadata = _gasTokenMetadata; + // Set sovereign weth token or create new if not provided + if (_sovereignWETHAddress == address(0)) { + // Create a wrapped token for WETH, with salt == 0 + WETHToken = _deployWrappedToken( + 0, // salt + abi.encode("Wrapped Ether", "WETH", 18) + ); + } else { + WETHToken = TokenWrapped(_sovereignWETHAddress); + wrappedAddressIsNotMintable[ + _sovereignWETHAddress + ] = _sovereignWETHAddressIsNotMintable; + } + } + + // Initialize OZ contracts + __ReentrancyGuard_init(); + } + + /** + * @notice Override the function to prevent the contract from being initialized with this initializer + */ + function initialize( + uint32, // _networkID + address, //_gasTokenAddress + uint32, //_gasTokenNetwork + IBasePolygonZkEVMGlobalExitRoot, //_globalExitRootManager + address, //_polygonRollupManager + bytes memory //_gasTokenMetadata + ) + external + override(IPolygonZkEVMBridgeV2, PolygonZkEVMBridgeV2) + initializer + { + revert InvalidInitializeFunction(); + } + + modifier onlyBridgeManager() { + if (bridgeManager != msg.sender) { + revert OnlyBridgeManager(); + } + _; + } + + /** + * @notice Updated bridge manager address + * @param _bridgeManager Bridge manager address + */ + function setBridgeManager( + address _bridgeManager + ) external onlyBridgeManager { + if (_bridgeManager == address(0)) revert NotValidBridgeManager(); + bridgeManager = _bridgeManager; + emit SetBridgeManager(bridgeManager); + } + + /** + * @notice Remap multiple wrapped tokens to a new sovereign token address + * @dev This function is a "multi/batch call" to `setSovereignTokenAddress` + * @param sovereignTokenAddresses Array of SovereignTokenAddress to remap + */ + function setMultipleSovereignTokenAddress( + uint32[] memory originNetworks, + address[] memory originTokenAddresses, + address[] memory sovereignTokenAddresses, + bool[] memory isNotMintable + ) external onlyBridgeManager { + require( + originNetworks.length == originTokenAddresses.length && + originTokenAddresses.length == sovereignTokenAddresses.length && + sovereignTokenAddresses.length == isNotMintable.length, + "Input array lengths mismatch" + ); + // Make multiple calls to setSovereignTokenAddress + for (uint256 i = 0; i < sovereignTokenAddresses.length; i++) { + _setSovereignTokenAddress( + originNetworks[i], + originTokenAddresses[i], + sovereignTokenAddresses[i], + isNotMintable[i] + ); + } + } + + /** + * @notice Remap a wrapped token to a new sovereign token address + * @dev This function is used to allow any existing token to be mapped with + * origin token. + * @notice If this function is called multiple times for the same existingTokenAddress, + * this will override the previous calls and only keep the last sovereignTokenAddress. + * @notice The tokenInfoToWrappedToken mapping value is replaced by the new sovereign address but it's not the case for the wrappedTokenToTokenInfo map where the value is added, this way user will always be able to withdraw their tokens + * @param originNetwork Origin network + * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param sovereignTokenAddress Address of the sovereign wrapped token + * @param isNotMintable Flag to indicate if the wrapped token is not mintable + */ + function setSovereignTokenAddress( + uint32 originNetwork, + address originTokenAddress, + address sovereignTokenAddress, + bool isNotMintable + ) external onlyBridgeManager { + _setSovereignTokenAddress( + originNetwork, + originTokenAddress, + sovereignTokenAddress, + isNotMintable + ); + } + + /** + * @notice Function to remap sovereign address + */ + function _setSovereignTokenAddress( + uint32 originNetwork, + address originTokenAddress, + address sovereignTokenAddress, + bool isNotMintable + ) internal { + // origin and sovereign token address are not 0 + if ( + originTokenAddress == address(0) || + sovereignTokenAddress == address(0) + ) { + revert InvalidZeroAddress(); + } + // originNetwork != current network, wrapped tokens are always from other networks + if (originNetwork == networkID) { + revert OriginNetworkInvalid(); + } + // Compute token info hash + bytes32 tokenInfoHash = keccak256( + abi.encodePacked(originNetwork, originTokenAddress) + ); + // Set the address of the wrapper + tokenInfoToWrappedToken[tokenInfoHash] = sovereignTokenAddress; + // Set the token info mapping + wrappedTokenToTokenInfo[sovereignTokenAddress] = TokenInformation( + originNetwork, + originTokenAddress + ); + wrappedAddressIsNotMintable[sovereignTokenAddress] = isNotMintable; + emit SetSovereignTokenAddress( + originNetwork, + originTokenAddress, + sovereignTokenAddress, + isNotMintable + ); + } + + /** + * @notice Remove the address of a remapped token from the mapping. Used to stop supporting legacy sovereign tokens + * @notice It also removes the token from the isNotMintable mapping + * @notice Although the token is removed from the mapping, the user will still be able to withdraw their tokens using tokenInfoToWrappedToken mapping + * @param sovereignTokenAddress Address of the sovereign wrapped token + */ + function removeSovereignTokenAddress( + address sovereignTokenAddress + ) external onlyBridgeManager { + // Only allow to remove already mapped tokens + TokenInformation memory tokenInfo = wrappedTokenToTokenInfo[ + sovereignTokenAddress + ]; + bytes32 tokenInfoHash = keccak256( + abi.encodePacked( + tokenInfo.originNetwork, + tokenInfo.originTokenAddress + ) + ); + + if ( + tokenInfoToWrappedToken[tokenInfoHash] == address(0) || + tokenInfoToWrappedToken[tokenInfoHash] == sovereignTokenAddress + ) { + revert TokenNotMapped(); + } + delete wrappedTokenToTokenInfo[sovereignTokenAddress]; + delete wrappedAddressIsNotMintable[sovereignTokenAddress]; + emit RemoveSovereignTokenAddress(sovereignTokenAddress); + } + + /** + * @notice Set the custom wrapper for weth + * @notice If this function is called multiple times this will override the previous calls and only keep the last sovereignTokenAddress. + * @param sovereignWETHTokenAddress Address of the sovereign weth token + * @param isNotMintable Flag to indicate if the wrapped token is not mintable + */ + function setSovereignWETHAddress( + address sovereignWETHTokenAddress, + bool isNotMintable + ) external onlyBridgeManager { + WETHToken = TokenWrapped(sovereignWETHTokenAddress); + wrappedAddressIsNotMintable[sovereignWETHTokenAddress] = isNotMintable; + emit SetSovereignWETHAddress(sovereignWETHTokenAddress, isNotMintable); + } + + /** + * @notice Moves old native or remapped token (legacy) to the new mapped token. If the token is mintable, it will be burnt and minted, otherwise it will be transferred + * @param legacyTokenAddress Address of legacy token to migrate + * @param amount Legacy token balance to migrate + */ + function migrateLegacyToken( + address legacyTokenAddress, + uint256 amount + ) external { + // Get current wrapped token address + TokenInformation memory legacyTokenInfo = wrappedTokenToTokenInfo[ + legacyTokenAddress + ]; + if (legacyTokenInfo.originTokenAddress == address(0)) { + revert TokenNotMapped(); + } + + // Check current token mapped is proposed updatedTokenAddress + address currentTokenAddress = tokenInfoToWrappedToken[ + keccak256( + abi.encodePacked( + legacyTokenInfo.originNetwork, + legacyTokenInfo.originTokenAddress + ) + ) + ]; + + if (currentTokenAddress == legacyTokenAddress) { + revert TokenAlreadyUpdated(); + } + + // Proceed to migrate the token + _bridgeWrappedAsset(TokenWrapped(legacyTokenAddress), amount); + _claimWrappedAsset( + TokenWrapped(currentTokenAddress), + msg.sender, + amount + ); + + // Trigger event + emit MigrateLegacyToken( + msg.sender, + legacyTokenAddress, + currentTokenAddress, + amount + ); + } + + /** + * @notice Burn tokens from wrapped token to execute the bridge, if the token is not mintable it will be transferred + * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + * @param tokenWrapped Wrapped token to burnt + * @param amount Amount of tokens + */ + function _bridgeWrappedAsset( + TokenWrapped tokenWrapped, + uint256 amount + ) internal override { + // The token is either (1) a correctly wrapped token from another network + // or (2) wrapped with custom contract from origin network + if (wrappedAddressIsNotMintable[address(tokenWrapped)]) { + // Don't use burn but transfer to bridge + IERC20Upgradeable(address(tokenWrapped)).safeTransferFrom( + msg.sender, + address(this), + amount + ); + } else { + // Burn tokens + tokenWrapped.burn(msg.sender, amount); + } + } + + /** + * @notice Mints tokens from wrapped token to proceed with the claim, if the token is not mintable it will be transferred + * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + * @param tokenWrapped Wrapped token to mint + * @param destinationAddress Minted token receiver + * @param amount Amount of tokens + */ + function _claimWrappedAsset( + TokenWrapped tokenWrapped, + address destinationAddress, + uint256 amount + ) internal override { + // If is not mintable transfer instead of mint + if (wrappedAddressIsNotMintable[address(tokenWrapped)]) { + // Transfer wETH + IERC20Upgradeable(address(tokenWrapped)).safeTransfer( + destinationAddress, + amount + ); + } else { + // Claim wETH + tokenWrapped.mint(destinationAddress, amount); + } + } +} diff --git a/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol new file mode 100644 index 000000000..5fb69e96d --- /dev/null +++ b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity 0.8.20; +import "../../PolygonZkEVMGlobalExitRootL2.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +// WARNING: not audited + +/** + * Contract responsible for managing the exit roots for the Sovereign chains and global exit roots + */ +contract GlobalExitRootManagerL2SovereignChain is + PolygonZkEVMGlobalExitRootL2, + Initializable +{ + // aggOracleAddress address + address public aggOracleAddress; + + // Inserted GER counter + uint256 public insertedGERCount; + + /** + * @dev Emitted when a new global exit root is inserted + */ + event InsertGlobalExitRoot(bytes32 indexed newGlobalExitRoot); + + /** + * @dev Emitted when the last global exit root is removed + */ + event RemoveLastGlobalExitRoot(bytes32 indexed removedGlobalExitRoot); + + modifier onlyAggOracleOrCoinbase() { + // Only allowed to be called by aggOracle or coinbase if aggOracle is zero + if ( + (aggOracleAddress == address(0) && block.coinbase != msg.sender) || + (aggOracleAddress != address(0) && aggOracleAddress != msg.sender) + ) { + revert OnlyAggOracleOrCoinbase(); + } + _; + } + + /** + * @param _bridgeAddress PolygonZkEVMBridge contract address + */ + constructor( + address _bridgeAddress + ) PolygonZkEVMGlobalExitRootL2(_bridgeAddress) { + _disableInitializers(); + } + + /** + * @notice Initialize contract setting the aggOracleAddress + */ + function initialize( + address _aggOracleAddress + ) external virtual initializer { + // set aggOracleAddress + aggOracleAddress = _aggOracleAddress; + } + + /** + * @notice Insert a new global exit root + * @param _newRoot new global exit root to insert + */ + function insertGlobalExitRoot( + bytes32 _newRoot + ) external onlyAggOracleOrCoinbase { + // do not insert GER if already set + if (globalExitRootMap[_newRoot] == 0) { + globalExitRootMap[_newRoot] = ++insertedGERCount; + emit InsertGlobalExitRoot(_newRoot); + } else { + revert GlobalExitRootAlreadySet(); + } + } + + /** + * @notice Remove last global exit roots + * @param gersToRemove Array of gers to remove in inserted order where first element of the array is the last inserted + */ + function removeLastGlobalExitRoots( + bytes32[] calldata gersToRemove + ) external onlyAggOracleOrCoinbase { + // Can't remove if not enough roots have been inserted + if (gersToRemove.length > insertedGERCount) { + revert NotEnoughGlobalExitRootsInserted(); + } + // Iterate through the array of roots to remove them one by one + for (uint256 i = 0; i < gersToRemove.length; i++) { + bytes32 rootToRemove = gersToRemove[i]; + + // Check that the root to remove is the last inserted + uint256 lastInsertedIndex = globalExitRootMap[rootToRemove]; + if (lastInsertedIndex != insertedGERCount) { + revert NotLastInsertedGlobalExitRoot(); + } + + // Remove from the mapping + delete globalExitRootMap[rootToRemove]; // Delete from the mapping + // Decrement the counter + insertedGERCount--; + + // Emit the removal event + emit RemoveLastGlobalExitRoot(rootToRemove); + } + } +} diff --git a/deployment/v2/1_createGenesis.ts b/deployment/v2/1_createGenesis.ts index 702003af8..d9fd2fe03 100644 --- a/deployment/v2/1_createGenesis.ts +++ b/deployment/v2/1_createGenesis.ts @@ -59,7 +59,7 @@ const zkevmAddressL2 = ethers.ZeroAddress; async function main() { // Constant variables const attemptsDeployProxy = 20; - const balanceBrige = BigInt("0xffffffffffffffffffffffffffffffff"); // 128 bits + const balanceBridge = BigInt("0xffffffffffffffffffffffffffffffff"); // 128 bits let timelockAdminAddress; let initialZkEVMDeployerOwner; @@ -75,9 +75,9 @@ async function main() { let proxyAdminAddress; let finalProxyAdminAddress; - let finalTimelockContractAdress; + let finalTimelockContractAddress; - let finalzkEVMDeployerAdress; + let finalZkEVMDeployerAddress; const finalGlobalExitRootL2ProxyAddress = globalExitRootL2Address; @@ -90,6 +90,7 @@ async function main() { // Check if it's mainnet deployment const isMainnet = deployParameters["isMainnet"] === true ? true : false; + let isSovereignChain = deployParameters["isSovereignChain"] === true ? true : false; if (isMainnet === true) { timelockAdminAddress = mainnetMultisig; @@ -97,8 +98,8 @@ async function main() { salt = "0x0000000000000000000000000000000000000000000000000000000000000000"; // salt mock initialZkEVMDeployerOwner = mainnetInitialZkEVMDeployerOwner; - finalzkEVMDeployerAdress = mainnetZkEVMDeployerAddress; - finalTimelockContractAdress = mainnetZkEVMTimelockAddress; + finalZkEVMDeployerAddress = mainnetZkEVMDeployerAddress; + finalTimelockContractAddress = mainnetZkEVMTimelockAddress; finalProxyAdminAddress = mainnetProxyAdminAddress; finalBridgeImplAddress = mainnetZkEVMBridgeImplementationAddress; finalBridgeProxyAddress = mainnetZkEVMBridgeProxyAddress; @@ -135,7 +136,7 @@ async function main() { if (isMainnet === false) { finalDeployer = deployer.address; finalKeylessDeployer = keylessDeployer; - finalzkEVMDeployerAdress = zkEVMDeployerContract.target; + finalZkEVMDeployerAddress = zkEVMDeployerContract.target; } /* * Deploy Bridge @@ -163,7 +164,8 @@ async function main() { } // Deploy implementation PolygonZkEVMBridge - const polygonZkEVMBridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2", deployer); + const bridgeContractName = isSovereignChain ? "BridgeL2SovereignChain": "PolygonZkEVMBridgeV2"; + const polygonZkEVMBridgeFactory = await ethers.getContractFactory(bridgeContractName, deployer); const deployTransactionBridge = (await polygonZkEVMBridgeFactory.getDeployTransaction()).data; // Mandatory to override the gasLimit since the estimation with create are mess up D: const overrideGasLimit = BigInt(5500000); @@ -211,14 +213,15 @@ async function main() { finalBridgeProxyAddress = proxyBridgeAddress; } - // Import OZ manifest the deployed contracts, its enough to import just the proyx, the rest are imported automatically ( admin/impl) + // Import OZ manifest the deployed contracts, its enough to import just the proxy, the rest are imported automatically ( admin/impl) await upgrades.forceImport(proxyBridgeAddress as string, polygonZkEVMBridgeFactory, "transparent" as any); /* *Deployment Global exit root manager */ + const globalExitRootContractName = isSovereignChain ? "GlobalExitRootManagerL2SovereignChain": "PolygonZkEVMGlobalExitRootL2"; const PolygonZkEVMGlobalExitRootL2Factory = await ethers.getContractFactory( - "PolygonZkEVMGlobalExitRootL2", + globalExitRootContractName, deployer ); let polygonZkEVMGlobalExitRootL2; @@ -257,12 +260,12 @@ async function main() { ); await timelockContract.waitForDeployment(); if (isMainnet === false) { - finalTimelockContractAdress = timelockContract.target; + finalTimelockContractAddress = timelockContract.target; } // Transfer ownership of the proxyAdmin to timelock const proxyAdminInstance = proxyAdminFactory.attach(proxyAdminAddress as string) as ProxyAdmin; - await (await proxyAdminInstance.connect(deployer).transferOwnership(finalTimelockContractAdress as string)).wait(); + await (await proxyAdminInstance.connect(deployer).transferOwnership(finalTimelockContractAddress as string)).wait(); // Recreate genesis with the current information: @@ -272,7 +275,7 @@ async function main() { contractName: "PolygonZkEVMDeployer", balance: "0", nonce: zkEVMDeployerInfo.nonce.toString(), - address: finalzkEVMDeployerAdress, + address: finalZkEVMDeployerAddress, bytecode: zkEVMDeployerInfo.bytecode, storage: zkEVMDeployerInfo.storage, }); @@ -291,7 +294,7 @@ async function main() { // Bridge implementation const bridgeImplementationInfo = await getAddressInfo(bridgeImplementationAddress as string); genesis.push({ - contractName: "PolygonZkEVMBridge implementation", + contractName: `${bridgeContractName}`, balance: "0", nonce: bridgeImplementationInfo.nonce.toString(), address: finalBridgeImplAddress, @@ -306,9 +309,9 @@ async function main() { bridgeProxyInfo.storage[_IMPLEMENTATION_SLOT] = ethers.zeroPadValue(finalBridgeImplAddress as string, 32); genesis.push({ - contractName: "PolygonZkEVMBridge proxy", - balance: balanceBrige, - nonce: bridgeProxyInfo.nonce.toString(), + contractName: `${bridgeContractName} proxy`, + balance: balanceBridge, + nonce: bridgeProxyInfo.nonce.toString(), address: finalBridgeProxyAddress, bytecode: bridgeProxyInfo.bytecode, storage: bridgeProxyInfo.storage, @@ -325,7 +328,7 @@ async function main() { } genesis.push({ - contractName: "PolygonZkEVMGlobalExitRootL2 implementation", + contractName: `${globalExitRootContractName}`, balance: "0", nonce: implGlobalExitRootL2Info.nonce.toString(), address: finalGlobalExitRootL2ImplAddress, @@ -343,7 +346,7 @@ async function main() { ); genesis.push({ - contractName: "PolygonZkEVMGlobalExitRootL2 proxy", + contractName: `${globalExitRootContractName} proxy`, balance: "0", nonce: proxyGlobalExitRootL2Info.nonce.toString(), address: finalGlobalExitRootL2ProxyAddress, @@ -355,7 +358,7 @@ async function main() { const timelockInfo = await getAddressInfo(timelockContract.target); /* - * Since roles are used, most storage are writted in peusdoRandom storage slots + * Since roles are used, most storage is written in pseudoRandom storage slots * bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE"); * bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); * bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); @@ -398,7 +401,7 @@ async function main() { contractName: "PolygonZkEVMTimelock", balance: "0", nonce: timelockInfo.nonce.toString(), - address: finalTimelockContractAdress, + address: finalTimelockContractAddress, bytecode: timelockInfo.bytecode, storage: timelockInfo.storage, }); @@ -483,9 +486,9 @@ async function getAddressInfo(address: string | Addressable) { if (valueAdminSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { storage[_ADMIN_SLOT] = valueAdminSlot; } - const valuImplementationSlot = await ethers.provider.getStorage(address, _IMPLEMENTATION_SLOT); - if (valuImplementationSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { - storage[_IMPLEMENTATION_SLOT] = valuImplementationSlot; + const valueImplementationSlot = await ethers.provider.getStorage(address, _IMPLEMENTATION_SLOT); + if (valueImplementationSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { + storage[_IMPLEMENTATION_SLOT] = valueImplementationSlot; } return {nonce, bytecode, storage}; diff --git a/deployment/v2/4_createRollup.ts b/deployment/v2/4_createRollup.ts index 3d0878648..fa06e8b4b 100644 --- a/deployment/v2/4_createRollup.ts +++ b/deployment/v2/4_createRollup.ts @@ -11,6 +11,7 @@ import {HardhatEthersSigner} from "@nomicfoundation/hardhat-ethers/signers"; const {create2Deployment} = require("../helpers/deployment-helpers"); const pathGenesis = path.join(__dirname, "./genesis.json"); +import {processorUtils} from "@0xpolygonhermez/zkevm-commonjs"; const createRollupParameters = require("./create_rollup_parameters.json"); const genesis = require("./genesis.json"); @@ -21,9 +22,8 @@ const pathOutputJson = path.join(__dirname, "./create_rollup_output.json"); import { PolygonRollupManager, - PolygonZkEVMV2, + PolygonZkEVMEtrog, PolygonZkEVMBridgeV2, - PolygonValidium, PolygonValidiumEtrog, } from "../../typechain-types"; @@ -66,10 +66,10 @@ async function main() { consensusContract, } = createRollupParameters; - const supportedConensus = ["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonPessimisticConsensus"]; + const supportedConsensus = ["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonPessimisticConsensus"]; - if (!supportedConensus.includes(consensusContract)) { - throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConensus}`); + if (!supportedConsensus.includes(consensusContract)) { + throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConsensus}`); } const dataAvailabilityProtocol = createRollupParameters.dataAvailabilityProtocol || "PolygonDataCommittee"; @@ -77,7 +77,7 @@ async function main() { const supporteDataAvailabilityProtocols = ["PolygonDataCommittee"]; if ( - consensusContract.includes("PolygonValidium") && + consensusContract.includes("PolygonValidiumEtrog") && !supporteDataAvailabilityProtocols.includes(dataAvailabilityProtocol) ) { throw new Error( @@ -133,11 +133,17 @@ async function main() { } // Load Rollup manager - const PolgonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); - const rollupManagerContract = PolgonRollupManagerFactory.attach( + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); + const rollupManagerContract = PolygonRollupManagerFactory.attach( deployOutput.polygonRollupManagerAddress ) as PolygonRollupManager; + // Load global exit root manager + const globalExitRootManagerFactory = await ethers.getContractFactory("PolygonZkEVMGlobalExitRootV2", deployer); + const globalExitRootManagerContract = globalExitRootManagerFactory.attach( + deployOutput.polygonZkEVMGlobalExitRootAddress + ) as PolygonRollupManager; + const DEFAULT_ADMIN_ROLE = ethers.ZeroHash; if ((await rollupManagerContract.hasRole(DEFAULT_ADMIN_ROLE, deployer.address)) == false) { throw new Error( @@ -227,17 +233,16 @@ async function main() { let gasTokenAddress, gasTokenNetwork, gasTokenMetadata; + // Get bridge instance + const bridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2", deployer); + const polygonZkEVMBridgeContract = bridgeFactory.attach( + deployOutput.polygonZkEVMBridgeAddress + ) as PolygonZkEVMBridgeV2; if ( createRollupParameters.gasTokenAddress && createRollupParameters.gasTokenAddress != "" && createRollupParameters.gasTokenAddress != ethers.ZeroAddress ) { - // Get bridge instance - const bridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2", deployer); - const polygonZkEVMBridgeContract = bridgeFactory.attach( - deployOutput.polygonZkEVMBridgeAddress - ) as PolygonZkEVMBridgeV2; - // Get token metadata gasTokenMetadata = await polygonZkEVMBridgeContract.getTokenMetadata(createRollupParameters.gasTokenAddress); @@ -259,9 +264,10 @@ async function main() { gasTokenMetadata = "0x"; } + const nonce = await currentProvider.getTransactionCount(rollupManagerContract.target); const newZKEVMAddress = ethers.getCreateAddress({ from: rollupManagerContract.target as string, - nonce: await currentProvider.getTransactionCount(rollupManagerContract.target), + nonce: nonce, }); // Create new rollup @@ -283,8 +289,8 @@ async function main() { console.log("#######################\n"); console.log(`Created new ${consensusContract} Rollup:`, newZKEVMAddress); - if (consensusContract.includes("PolygonValidium") && dataAvailabilityProtocol === "PolygonDataCommittee") { - // deploy data commitee + if (consensusContract.includes("PolygonValidiumEtrog") && dataAvailabilityProtocol === "PolygonDataCommittee") { + // deploy data committee const PolygonDataCommitteeContract = (await ethers.getContractFactory("PolygonDataCommittee", deployer)) as any; let polygonDataCommittee; @@ -306,7 +312,7 @@ async function main() { await polygonDataCommittee?.waitForDeployment(); // Load data commitee - const PolygonValidiumContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonValidium; + const PolygonValidiumContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonValidiumEtrog; // add data commitee to the consensus contract if ((await PolygonValidiumContract.admin()) == deployer.address) { await ( @@ -339,12 +345,42 @@ async function main() { } } - // Add the first batch of the created rollup - const newZKEVMContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonZkEVMV2; - - if (consensusContract != "PolygonPessimisticConsensus") { - const batchData = { - transactions: await newZKEVMContract.generateInitializeTransaction( + let batchData; + if (consensusContract === "PolygonPessimisticConsensus") { + // Get last GER + const lastGER = await globalExitRootManagerContract.getLastGlobalExitRoot(); + const lastBlock = await ethers.provider.getBlock("latest"); + const timestamp = lastBlock?.timestamp; + const uTx = await polygonZkEVMBridgeContract.initialize.populateTransaction( + rollupID, + gasTokenAddress, + gasTokenNetwork, + globalExitRootManagerContract.target, + rollupManagerContract.target, + gasTokenMetadata as any + ); + uTx.gasPrice = BigInt(0); + uTx.gasLimit = BigInt(3000000); // 30M of gas + uTx.chainId = chainID; + uTx.type = 0; + //uTx.type = 1; + const signer = ethers.HDNodeWallet.fromMnemonic( + ethers.Mnemonic.fromPhrase("test test test test test test test test test test test junk"), + "m/44'/60'/0'/0/0" + ).connect(currentProvider); + const signedTx = await signer.signTransaction(uTx); + const customData = processorUtils.rawTxToCustomRawTx(signedTx); + batchData = { + batchL2Data: customData, + globalExitRoot: lastGER, + timestamp: timestamp, + sequencer: trustedSequencer, + }; + } else { + // Add the first batch of the created rollup + const newZKEVMContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonZkEVMEtrog; + batchData = { + batchL2Data: await newZKEVMContract.generateInitializeTransaction( rollupID, gasTokenAddress, gasTokenNetwork, @@ -354,9 +390,8 @@ async function main() { timestamp: timestampReceipt, sequencer: trustedSequencer, }; - outputJson.firstBatchData = batchData; } - + outputJson.firstBatchData = batchData; outputJson.genesis = genesis.root; outputJson.createRollupBlockNumber = blockDeploymentRollup.number; outputJson.rollupAddress = newZKEVMAddress; @@ -370,3 +405,4 @@ main().catch((e) => { console.error(e); process.exit(1); }); + diff --git a/deployment/v2/README.md b/deployment/v2/README.md index 3e4e37a62..520883a74 100644 --- a/deployment/v2/README.md +++ b/deployment/v2/README.md @@ -20,12 +20,12 @@ cd deployment cp deploy_parameters.json.example deploy_parameters.json ``` -Fill created `deploy_parameters.json` with appropiate parameters. +Fill created `deploy_parameters.json` with appropriate parameters. See below for more information about the `deploy_parameters.json` The first step is deploying and verifying the `PolygonZkEVMDeployer`, this will be the factory for deterministic contracts, the address of the contracts will depend on the `salt` and the `initialZkEVMDeployerOwner` -This contrat is deployed using a keyless deployment, therefore the gasPrice is hardcoded. +This contract is deployed using a keyless deployment, therefore the gasPrice is hardcoded. The value is on `100 gweis`, if it's necessary to update it go to `helpers/deployment-helpers.js` and update the `gasPriceKeylessDeployment` constant. Note that this operation will change all the deterministic address deployed. @@ -38,7 +38,7 @@ To deploy on testnet is necessary a token MATIC contract, therefore, there's ano To deploy on testnet use:`deploy:testnet:ZkEVM:${network}` -In other cases use fullfill `maticTokenAddress` in the `deploy_parameters.json` and run `deploy:ZkEVM:${network}` +In other cases use fulfill `maticTokenAddress` in the `deploy_parameters.json` and run `deploy:ZkEVM:${network}` ``` npm run deploy:testnet:ZkEVM:goerli @@ -51,12 +51,12 @@ To verify contracts use `npm run verify:ZkEVM:${network}` npm run verify:ZkEVM:goerli ``` -A new folder will be created witth the following name `deployments/${network}_$(date +%s)` with all the output information and the OZ proxy information. +A new folder will be created with the following name `deployments/${network}_$(date +%s)` with all the output information and the OZ proxy information. ## deploy-parameters.json - `test`: bool, Indicate if it's a test deployment, which will fund the deployer address with pre minted ether and will give more powers to the deployer address to make easier the flow. -- `timelockAdminAddress`: address, Timelock owner address, able to send start an upgradability process via timelock +- `timelockAdminAddress`: address, Timelock owner address, able to send start an upgradeability process via timelock - `minDelayTimelock`: number, Minimum timelock delay, - `salt`: bytes32, Salt used in `PolygonZkEVMDeployer` to deploy deterministic contracts, such as the PolygonZkEVMBridge - `initialZkEVMDeployerOwner`: address, Initial owner of the `PolygonZkEVMDeployer` @@ -64,9 +64,9 @@ A new folder will be created witth the following name `deployments/${network}_$( - `trustedAggregator`: address, Trusted aggregator address - `trustedAggregatorTimeout`: uint64, If a sequence is not verified in this timeout everyone can verify it - `pendingStateTimeout`: uint64, Once a pending state exceeds this timeout it can be consolidated by everyone -- `emergencyCouncilAddress`:address, Emergency council addres -- `polTokenAddress`: address, Matic token address, only if deploy on testnet can be left blank and will fullfilled by the scripts. -- `zkEVMDeployerAddress`: address, Address of the `PolygonZkEVMDeployer`. Can be left blank, will be fullfilled automatically with the `deploy:deployer:ZkEVM:goerli` script. +- `emergencyCouncilAddress`:address, Emergency council address +- `polTokenAddress`: address, Matic token address, only if deploy on testnet can be left blank and will fulfilled by the scripts. +- `zkEVMDeployerAddress`: address, Address of the `PolygonZkEVMDeployer`. Can be left blank, will be fulfilled automatically with the `deploy:deployer:ZkEVM:goerli` script. ## create_rollup_parameters.json @@ -74,7 +74,7 @@ A new folder will be created witth the following name `deployments/${network}_$( - `trustedSequencerURL`: string, trustedSequencer URL - `networkName`: string, networkName - `description`: string, Description of the new rollup type -- `trustedSequencer`: address, trusted sequencer addresss +- `trustedSequencer`: address, trusted sequencer address - `chainID`: uint64, chainID of the new rollup - `adminZkEVM`: address, Admin address, can adjust Rollup parameters - `forkID`: uint64, Fork ID of the new rollup, indicates the prover (zkROM/executor) version @@ -84,13 +84,13 @@ A new folder will be created witth the following name `deployments/${network}_$( ### Optional Parameters on both parameters - `deployerPvtKey`: string, pvtKey of the deployer, overrides the address in `MNEMONIC` of `.env` if exist -- `maxFeePerGas`: string, Set `maxFeePerGas`, must define aswell `maxPriorityFeePerGas` to use it -- `maxPriorityFeePerGas`: string, Set `maxPriorityFeePerGas`, must define aswell `maxFeePerGas` to use it +- `maxFeePerGas`: string, Set `maxFeePerGas`, must define as well `maxPriorityFeePerGas` to use it +- `maxPriorityFeePerGas`: string, Set `maxPriorityFeePerGas`, must define as well `maxFeePerGas` to use it - `multiplierGas`: number, Gas multiplier with 3 decimals. If `maxFeePerGas` and `maxPriorityFeePerGas` are set, this will not take effect -- `dataAvailabilityProtocol`: string, Data availability protocol, only mandatory/used when consensus contract is a Validiums, currently the only supported value is: `PolygonDataCommittee` +- `dataAvailabilityProtocol`: string, Data availability protocol, only mandatory/used when consensus contract is a Validium, currently the only supported value is: `PolygonDataCommittee` ## Notes - Since there are deterministic address you cannot deploy twice on the same network using the same `salt` and `initialZkEVMDeployerOwner`. Changing one of them is enough to make a new deployment. -- It's mandatory to delete the `.openzeppelin` upgradebility information in order to make a new deployment -- `genesis.json` has been generated using the tool: `1_createGenesis`, this script depends on the `deploy_parameters` aswell. +- It's mandatory to delete the `.openzeppelin` upgradeability information in order to make a new deployment +- `genesis.json` has been generated using the tool: `1_createGenesis`, this script depends on the `deploy_parameters` as well. diff --git a/deployment/v2/deploy_parameters.json.example b/deployment/v2/deploy_parameters.json.example index d57ad7c80..9794bd452 100644 --- a/deployment/v2/deploy_parameters.json.example +++ b/deployment/v2/deploy_parameters.json.example @@ -14,5 +14,6 @@ "deployerPvtKey": "", "maxFeePerGas":"", "maxPriorityFeePerGas":"", - "multiplierGas": "" + "multiplierGas": "", + "isSovereignChain": false } diff --git a/hardhat.config.ts b/hardhat.config.ts index 3cf06de28..c41a38d42 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -75,6 +75,16 @@ const config: HardhatUserConfig = { }, ], overrides: { + "contracts/v2/sovereignChains/BridgeL2SovereignChain.sol": { + version: "0.8.20", + settings: { + optimizer: { + enabled: true, + runs: 0, + }, + evmVersion: "shanghai", + }, // try yul optimizer + }, "contracts/v2/PolygonRollupManager.sol": { version: "0.8.20", settings: { diff --git a/package.json b/package.json index b776c2f8d..1ce8833ba 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "hardhat": "^2.22.3", "hardhat-dependency-compiler": "^1.1.3", "prettier": "^2.8.8", - "prettier-plugin-solidity": "^1.1.3", + "prettier-plugin-solidity": "^1.4.1", "solc-0.8": "npm:solc@0.8.20", "solidity-docgen": "^0.5.17" }, diff --git a/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts b/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts new file mode 100644 index 000000000..1013ec9f2 --- /dev/null +++ b/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts @@ -0,0 +1,1590 @@ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + ERC20PermitMock, + GlobalExitRootManagerL2SovereignChain, + BridgeL2SovereignChain, + TokenWrapped, +} from "../../typechain-types"; +import {takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers"; +import {processorUtils, contractUtils, MTBridge, mtBridgeUtils} from "@0xpolygonhermez/zkevm-commonjs"; +const {calculateSnarkInput, calculateAccInputHash, calculateBatchHashData} = contractUtils; +const MerkleTreeBridge = MTBridge; +const {verifyMerkleProof, getLeafValue} = mtBridgeUtils; +import {setBalance} from "@nomicfoundation/hardhat-network-helpers"; + +function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { + return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); +} +const _GLOBAL_INDEX_MAINNET_FLAG = 2n ** 64n; + +function computeGlobalIndex(indexLocal: any, indexRollup: any, isMainnet: Boolean) { + if (isMainnet === true) { + return BigInt(indexLocal) + _GLOBAL_INDEX_MAINNET_FLAG; + } else { + return BigInt(indexLocal) + BigInt(indexRollup) * 2n ** 32n; + } +} + +describe("SovereignChainBridge Gas tokens tests", () => { + upgrades.silenceWarnings(); + + let sovereignChainBridgeContract: BridgeL2SovereignChain; + let polTokenContract: ERC20PermitMock; + let sovereignChainGlobalExitRoot: GlobalExitRootManagerL2SovereignChain; + + let deployer: any; + let rollupManager: any; + let acc1: any; + let bridgeManager: any; + + const tokenName = "Matic Token"; + const tokenSymbol = "MATIC"; + const decimals = 18; + const tokenInitialBalance = ethers.parseEther("20000000"); + const metadataToken = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [tokenName, tokenSymbol, decimals] + ); + const networkIDMainnet = 0; + const networkIDRollup = 1; + const networkIDRollup2 = 2; + + const LEAF_TYPE_ASSET = 0; + const LEAF_TYPE_MESSAGE = 1; + + let gasTokenAddress: any; + let gasTokenNetwork: any; + let gasTokenMetadata: any; + let WETHToken: TokenWrapped; + + beforeEach("Deploy contracts", async () => { + // load signers + [deployer, rollupManager, acc1, bridgeManager] = await ethers.getSigners(); + + // Set trusted sequencer as coinbase for sovereign chains + await ethers.provider.send("hardhat_setCoinbase", [deployer.address]); + // deploy PolygonZkEVMBridge + const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) as unknown as BridgeL2SovereignChain; + + // deploy global exit root manager + const SovereignChainGlobalExitRootFactory = await ethers.getContractFactory( + "GlobalExitRootManagerL2SovereignChain" + ); + sovereignChainGlobalExitRoot = await SovereignChainGlobalExitRootFactory.deploy( + sovereignChainBridgeContract.target + ); + + // deploy weth token by bridge + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + WETHToken = await tokenWrappedFactory.connect(bridgeMock).deploy( + tokenName, + tokenSymbol, + decimals, + {gasPrice: 0} + ); + + gasTokenAddress = polTokenContract.target; + gasTokenNetwork = 0; + gasTokenMetadata = metadataToken; + + await sovereignChainBridgeContract.initialize( + networkIDRollup2, + polTokenContract.target, // zero for ether + 0, // zero for ether + sovereignChainGlobalExitRoot.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + WETHToken.target, + false + ); + expect(await sovereignChainBridgeContract.WETHToken()).to.be.equal(WETHToken.target); + }); + + it("should claim message from not mintable remapped gas (WETH) token", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDRollup; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // deploy sovereign + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const sovereignToken = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRoot.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + // Remap weth token + await expect(sovereignChainBridgeContract.connect(bridgeManager).setSovereignWETHAddress(sovereignToken.target, true)) + .to.emit(sovereignChainBridgeContract, "SetSovereignWETHAddress") + .withArgs(sovereignToken.target, true); + // try claim without balance to transfer (from bridge) + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.revertedWith("ERC20: transfer amount exceeds balance"); + // Transfer tokens to bridge + await sovereignToken.transfer(sovereignChainBridgeContract.target, amount); + const balanceBridge = await sovereignToken.balanceOf(sovereignChainBridgeContract.target); + + // Check balances before claim + expect(balanceBridge).to.be.equal(amount); + // Claim message + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, sovereignToken.target, destinationAddress, amount); + + // Check balances after claim + expect(await sovereignToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(ethers.parseEther("0")); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should check the constructor parameters", async () => { + expect(await sovereignChainBridgeContract.globalExitRootManager()).to.be.equal( + sovereignChainGlobalExitRoot.target + ); + expect(await sovereignChainBridgeContract.networkID()).to.be.equal(networkIDRollup2); + expect(await sovereignChainBridgeContract.polygonRollupManager()).to.be.equal(rollupManager.address); + + expect(await sovereignChainBridgeContract.gasTokenAddress()).to.be.equal(gasTokenAddress); + expect(await sovereignChainBridgeContract.gasTokenNetwork()).to.be.equal(gasTokenNetwork); + expect(await sovereignChainBridgeContract.gasTokenMetadata()).to.be.equal(gasTokenMetadata); + }); + + it("should check the emergency state", async () => { + expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(false); + + await expect(sovereignChainBridgeContract.activateEmergencyState()).to.be.revertedWithCustomError( + sovereignChainBridgeContract, + "OnlyRollupManager" + ); + await expect(sovereignChainBridgeContract.connect(rollupManager).activateEmergencyState()).to.emit( + sovereignChainBridgeContract, + "EmergencyStateActivated" + ); + + expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(true); + + await expect( + sovereignChainBridgeContract.connect(deployer).deactivateEmergencyState() + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyRollupManager"); + + await expect(sovereignChainBridgeContract.connect(rollupManager).deactivateEmergencyState()).to.emit( + sovereignChainBridgeContract, + "EmergencyStateDeactivated" + ); + + expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(false); + }); + + it("should SovereignChain bridge asset and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const mainnetExitRoot = ethers.ZeroHash; + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignRollup = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: 1} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "MsgValueNotZero"); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSSovereignRollup); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + }); + + it("should PolygonZkEVMBridge message and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const originAddress = deployer.address; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + const mainnetExitRoot = ethers.ZeroHash; + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignChain = merkleTree.getRoot(); + + // using gas TOkens cannot use bridge message with etther + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, { + value: amount, + }) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NoValueInMessagesOnGasTokenNetworks"); + + // Use bridgeMessageWETH instead! + + // cannot use value + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata, + { + value: amount, + } + ) + ).to.be.reverted; + + // Use bridgeMessageWETH instead! + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata + ) + ).to.be.revertedWith("ERC20: burn amount exceeds balance"); + + // Mock mint weth + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + + await WETHToken.connect(bridgeMock).mint(deployer.address, amount, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + expect(rootSCSovereignChain).to.be.equal(rootJSSovereignChain); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCSovereignChain)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCSovereignChain) + ).to.be.equal(true); + + // bridge message without value is fine + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, {}) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + 0, + metadata, + depositCount + 1n + ); + }); + + it("should SovereignChain bridge asset and message to check global exit root updates", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const mainnetExitRoot = ethers.ZeroHash; + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignChain = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(0); + expect(mainnetExitRoot).to.be.equal(ethers.ZeroHash); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + expect(rootSCSovereignChain).to.be.equal(rootJSSovereignChain); + + // Update global exit root + await expect(sovereignChainBridgeContract.updateGlobalExitRoot()); + + // no state changes since there are not any deposit pending to be updated + await sovereignChainBridgeContract.updateGlobalExitRoot(); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + expect(mainnetExitRoot).to.be.equal(mainnetExitRoot); + + // bridge message + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, false, metadata, { + value: amount, + }) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NoValueInMessagesOnGasTokenNetworks"); + + // Mock mint weth + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await WETHToken.connect(bridgeMock).mint(deployer.address, amount, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + false, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + deployer.address, + destinationNetwork, + destinationAddress, + amount, + metadata, + 1 + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + expect(mainnetExitRoot).to.be.equal(mainnetExitRoot); + + // Update global exit root + await sovereignChainBridgeContract.updateGlobalExitRoot(); + + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(2); + expect(mainnetExitRoot).to.not.be.equal(rootJSSovereignChain); + + // Just to have the metric of a low cost bridge Asset + const tokenAddress2 = WETHToken.target; // Ether + const amount2 = ethers.parseEther("10"); + await WETHToken.connect(bridgeMock).mint(deployer.address, amount2, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount2, + tokenAddress2, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + 0, // weth bridge + ethers.ZeroAddress, + destinationNetwork, + destinationAddress, + amount2, + "0x", + 2 + ) + .to.emit(WETHToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount2); + }); + + it("should claim Gas tokens from SovereignChain to SovereignChain", async () => { + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = acc1.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + const indexRollup = 5; + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + if (i == indexRollup) { + merkleTreeRollup.add(rootLocalRollup); + } else { + merkleTreeRollup.add(ethers.toBeHex(ethers.toQuantity(ethers.randomBytes(32)), 32)); + } + } + const rootRollup = merkleTreeRollup.getRoot(); + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRoot.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRoot, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const sovereignChainExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(sovereignChainExitRootSC).to.be.equal(rootRollup); + const mainnetExitRootSC = ethers.ZeroHash; + expect(mainnetExitRootSC).to.be.equal(mainnetExitRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rootRollup); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof rollup + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + /* + * claim + * Can't claim without native (ether) + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + rootLocalRollup, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.reverted; + + await setBalance(sovereignChainBridgeContract.target as any, amount); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + const initialBalance = await ethers.provider.getBalance(sovereignChainBridgeContract.target); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + { + gasPrice: 0, + } + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(initialBalance - amount).to.be.equal( + await ethers.provider.getBalance(sovereignChainBridgeContract.target) + ); + }); + + it("should claim tokens from SovereignChain to SovereignChain2", async () => { + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + merkleTreeRollup.add(rootLocalRollup); + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRoot.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRoot, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof local + const indexRollup = 5; + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + // claim + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); + const precalculateWrappedErc20 = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + salt, + hashInitCode + ); + const newWrappedToken = tokenWrappedFactory.attach(precalculateWrappedErc20) as TokenWrapped; + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.precalculatedWrapperAddress( + networkIDRollup, + tokenAddress, + tokenName, + tokenSymbol, + decimals + ) + ).to.be.equal(precalculateWrappedErc20); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(sovereignChainBridgeContract, "NewWrappedToken") + .withArgs(originNetwork, tokenAddress, precalculateWrappedErc20, metadata) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + const newTokenInfo = await sovereignChainBridgeContract.wrappedTokenToTokenInfo(precalculateWrappedErc20); + + expect(newTokenInfo.originNetwork).to.be.equal(networkIDRollup); + expect(newTokenInfo.originTokenAddress).to.be.equal(tokenAddress); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + + expect(await sovereignChainBridgeContract.tokenInfoToWrappedToken(salt)).to.be.equal(precalculateWrappedErc20); + + // Check the wrapper info + expect(await newWrappedToken.name()).to.be.equal(tokenName); + expect(await newWrappedToken.symbol()).to.be.equal(tokenSymbol); + expect(await newWrappedToken.decimals()).to.be.equal(decimals); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + + // Claim again the other leaf to mint tokens + const index2 = 1; + const proof2 = merkleTreeLocal.getProofTreeByIndex(index2); + + expect(verifyMerkleProof(leafValue, proof2, index2, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rollupExitRootSC)).to.be.equal(true); + + const globalIndex2 = computeGlobalIndex(index2, indexRollup, false); + await expect( + sovereignChainBridgeContract.claimAsset( + proof2, + proofRollup, + globalIndex2, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex2, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + // Burn Tokens + const depositCount = await sovereignChainBridgeContract.depositCount(); + const wrappedTokenAddress = newWrappedToken.target; + const newDestinationNetwork = networkIDRollup; + + const rollupExitRoot = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + + // create a new deposit + await expect(newWrappedToken.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(newWrappedToken, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + /* + * pre compute root merkle tree in Js + * const height = 32; + */ + const merkleTreeMainnet = new MerkleTreeBridge(height); + // Imporant calcualte leaf with origin token address no wrapped token address + const originTokenAddress = tokenAddress; + const metadataMainnet = metadata; // since the token does not belong to this network + const metadataHashMainnet = ethers.solidityPackedKeccak256(["bytes"], [metadataMainnet]); + + const leafValueMainnet = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + const leafValueMainnetSC = await sovereignChainBridgeContract.getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + + expect(leafValueMainnet).to.be.equal(leafValueMainnetSC); + merkleTreeMainnet.add(leafValueMainnet); + const rootJSMainnet = ethers.ZeroHash; + + // Tokens are burnt + expect(await newWrappedToken.totalSupply()).to.be.equal(amount * 2n); + expect(await newWrappedToken.balanceOf(destinationAddress)).to.be.equal(amount * 2n); + await expect( + sovereignChainBridgeContract.bridgeAsset( + newDestinationNetwork, + destinationAddress, + amount, + wrappedTokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataMainnet, + depositCount + ) + .to.emit(newWrappedToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(0); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + + // check merkle proof + const proofMainnet = merkleTreeMainnet.getProofTreeByIndex(0); + const indexMainnet = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValueMainnet, proofMainnet, indexMainnet, rootSCSovereignChain)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof( + leafValueMainnet, + proofMainnet, + indexMainnet, + rootSCSovereignChain + ) + ).to.be.equal(true); + }); + + it("should PolygonZkEVMBridge and sync the current root with events", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // gasToken + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + // create 3 new deposit + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + 1n + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + 2n + ); + + // Prepare merkle tree + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + + // Get the deposit's events + const filter = sovereignChainBridgeContract.filters.BridgeEvent( + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined + ); + const events = await sovereignChainBridgeContract.queryFilter(filter, 0, "latest"); + events.forEach((e) => { + const {args} = e; + const leafValue = getLeafValue( + args.leafType, + args.originNetwork, + args.originAddress, + args.destinationNetwork, + args.destinationAddress, + args.amount, + ethers.solidityPackedKeccak256(["bytes"], [args.metadata]) + ); + merkleTree.add(leafValue); + }); + + // Check merkle root with SC + const rootSC = await sovereignChainBridgeContract.getRoot(); + const rootJS = merkleTree.getRoot(); + + expect(rootSC).to.be.equal(rootJS); + }); + + it("should claim testing all the asserts", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + const globalIndex = computeGlobalIndex(index, index, false); + // Can't claim without tokens + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.reverted; + + await setBalance(sovereignChainBridgeContract.target as any, amount); + + // Check GlobalExitRoot invalid assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + mainnetExitRoot, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "GlobalExitRootInvalid"); + + // Check Invalid smt proof assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex + 1n, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount); + + // Check Already claimed_claim + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim ether", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + // claim weth + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(WETHToken, "Transfer") + .withArgs(ethers.ZeroAddress, deployer.address, amount); + + // Check balances after claim + expect(await WETHToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await WETHToken.totalSupply()).to.be.equal(amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim message", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + /* + * claim + * Can't claim a message as an assets + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + const balanceDeployer = await ethers.provider.getBalance(deployer.address); + + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(WETHToken, "Transfer") + .withArgs(ethers.ZeroAddress, deployer.address, amount); + + // Check balances after claim + expect(await WETHToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await WETHToken.totalSupply()).to.be.equal(amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); +}); diff --git a/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts b/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts new file mode 100644 index 000000000..ee44f4d37 --- /dev/null +++ b/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts @@ -0,0 +1,1603 @@ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + ERC20PermitMock, + GlobalExitRootManagerL2SovereignChain, + BridgeL2SovereignChain, + TokenWrapped, +} from "../../typechain-types"; +import {takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers"; +import {processorUtils, contractUtils, MTBridge, mtBridgeUtils} from "@0xpolygonhermez/zkevm-commonjs"; +const {calculateSnarkInput, calculateAccInputHash, calculateBatchHashData} = contractUtils; +const MerkleTreeBridge = MTBridge; +const {verifyMerkleProof, getLeafValue} = mtBridgeUtils; +import {setBalance} from "@nomicfoundation/hardhat-network-helpers"; + +function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { + return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); +} +const _GLOBAL_INDEX_MAINNET_FLAG = 2n ** 64n; + +function computeGlobalIndex(indexLocal: any, indexRollup: any, isMainnet: Boolean) { + if (isMainnet === true) { + return BigInt(indexLocal) + _GLOBAL_INDEX_MAINNET_FLAG; + } else { + return BigInt(indexLocal) + BigInt(indexRollup) * 2n ** 32n; + } +} + +describe("SovereignChainBridge Gas tokens tests", () => { + upgrades.silenceWarnings(); + + let sovereignChainBridgeContract: BridgeL2SovereignChain; + let polTokenContract: ERC20PermitMock; + let sovereignChainGlobalExitRoot: GlobalExitRootManagerL2SovereignChain; + + let deployer: any; + let rollupManager: any; + let acc1: any; + let bridgeManager: any; + + const tokenName = "Matic Token"; + const tokenSymbol = "MATIC"; + const decimals = 18; + const tokenInitialBalance = ethers.parseEther("20000000"); + const metadataToken = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [tokenName, tokenSymbol, decimals] + ); + const networkIDMainnet = 0; + const networkIDRollup = 1; + const networkIDRollup2 = 2; + + const LEAF_TYPE_ASSET = 0; + const LEAF_TYPE_MESSAGE = 1; + + let gasTokenAddress: any; + let gasTokenNetwork: any; + let gasTokenMetadata: any; + let WETHToken: TokenWrapped; + + beforeEach("Deploy contracts", async () => { + // load signers + [deployer, rollupManager, acc1, bridgeManager] = await ethers.getSigners(); + + // Set trusted sequencer as coinbase for sovereign chains + await ethers.provider.send("hardhat_setCoinbase", [deployer.address]); + // deploy PolygonZkEVMBridge + const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) as unknown as BridgeL2SovereignChain; + + // deploy global exit root manager + const SovereignChainGlobalExitRootFactory = await ethers.getContractFactory( + "GlobalExitRootManagerL2SovereignChain" + ); + sovereignChainGlobalExitRoot = await SovereignChainGlobalExitRootFactory.deploy( + sovereignChainBridgeContract.target + ); + + // deploy token + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + + gasTokenAddress = polTokenContract.target; + gasTokenNetwork = 0; + gasTokenMetadata = metadataToken; + + await sovereignChainBridgeContract.initialize( + networkIDRollup2, + polTokenContract.target, // zero for ether + 0, // zero for ether + sovereignChainGlobalExitRoot.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + ethers.ZeroAddress, + false + ); + + // calculate the weth address: + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const WETHName = "Wrapped Ether"; + const WETHSymbol = "WETH"; + const WETHDecimals = 18; + const metadataWETH = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [WETHName, WETHSymbol, WETHDecimals] + ); + + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataWETH]); + const precalculatedWeth = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + ethers.ZeroHash, // salt is zero + hashInitCode + ); + WETHToken = tokenWrappedFactory.attach(precalculatedWeth) as TokenWrapped; + + expect(await sovereignChainBridgeContract.WETHToken()).to.be.equal(WETHToken.target); + }); + + it("should claim message from not mintable remapped gas (WETH) token", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // deploy sovereign + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const sovereignToken = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRoot.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + // Remap weth token + await expect(sovereignChainBridgeContract.connect(bridgeManager).setSovereignWETHAddress(sovereignToken.target, true)) + .to.emit(sovereignChainBridgeContract, "SetSovereignWETHAddress") + .withArgs(sovereignToken.target, true); + // try claim without balance to transfer (from bridge) + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.revertedWith("ERC20: transfer amount exceeds balance"); + // Transfer tokens to bridge + await sovereignToken.transfer(sovereignChainBridgeContract.target, amount); + const balanceBridge = await sovereignToken.balanceOf(sovereignChainBridgeContract.target); + + // Check balances before claim + expect(balanceBridge).to.be.equal(amount); + // Claim message + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, sovereignToken.target, destinationAddress, amount); + + // Check balances after claim + expect(await sovereignToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(ethers.parseEther("0")); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should check the constructor parameters", async () => { + expect(await sovereignChainBridgeContract.globalExitRootManager()).to.be.equal( + sovereignChainGlobalExitRoot.target + ); + expect(await sovereignChainBridgeContract.networkID()).to.be.equal(networkIDRollup2); + expect(await sovereignChainBridgeContract.polygonRollupManager()).to.be.equal(rollupManager.address); + + expect(await sovereignChainBridgeContract.gasTokenAddress()).to.be.equal(gasTokenAddress); + expect(await sovereignChainBridgeContract.gasTokenNetwork()).to.be.equal(gasTokenNetwork); + expect(await sovereignChainBridgeContract.gasTokenMetadata()).to.be.equal(gasTokenMetadata); + }); + + it("should check the emergency state", async () => { + expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(false); + + await expect(sovereignChainBridgeContract.activateEmergencyState()).to.be.revertedWithCustomError( + sovereignChainBridgeContract, + "OnlyRollupManager" + ); + await expect(sovereignChainBridgeContract.connect(rollupManager).activateEmergencyState()).to.emit( + sovereignChainBridgeContract, + "EmergencyStateActivated" + ); + + expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(true); + + await expect( + sovereignChainBridgeContract.connect(deployer).deactivateEmergencyState() + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyRollupManager"); + + await expect(sovereignChainBridgeContract.connect(rollupManager).deactivateEmergencyState()).to.emit( + sovereignChainBridgeContract, + "EmergencyStateDeactivated" + ); + + expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(false); + }); + + it("should SovereignChain bridge asset and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const mainnetExitRoot = ethers.ZeroHash; + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignRollup = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: 1} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "MsgValueNotZero"); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSSovereignRollup); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + }); + + it("should PolygonZkEVMBridge message and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const originAddress = deployer.address; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + const mainnetExitRoot = ethers.ZeroHash; + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignChain = merkleTree.getRoot(); + + // using gas TOkens cannot use bridge message with etther + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, { + value: amount, + }) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NoValueInMessagesOnGasTokenNetworks"); + + // Use bridgeMessageWETH instead! + + // cannot use value + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata, + { + value: amount, + } + ) + ).to.be.reverted; + + // Use bridgeMessageWETH instead! + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata + ) + ).to.be.revertedWith("ERC20: burn amount exceeds balance"); + + // Mock mint weth + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + + await WETHToken.connect(bridgeMock).mint(deployer.address, amount, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + expect(rootSCSovereignChain).to.be.equal(rootJSSovereignChain); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCSovereignChain)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCSovereignChain) + ).to.be.equal(true); + + // bridge message without value is fine + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, {}) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + 0, + metadata, + depositCount + 1n + ); + }); + + it("should SovereignChain bridge asset and message to check global exit root updates", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const mainnetExitRoot = ethers.ZeroHash; + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignChain = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(0); + expect(mainnetExitRoot).to.be.equal(ethers.ZeroHash); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + expect(rootSCSovereignChain).to.be.equal(rootJSSovereignChain); + + // Update global exit root + await expect(sovereignChainBridgeContract.updateGlobalExitRoot()); + + // no state changes since there are not any deposit pending to be updated + await sovereignChainBridgeContract.updateGlobalExitRoot(); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + expect(mainnetExitRoot).to.be.equal(mainnetExitRoot); + + // bridge message + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, false, metadata, { + value: amount, + }) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NoValueInMessagesOnGasTokenNetworks"); + + // Mock mint weth + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await WETHToken.connect(bridgeMock).mint(deployer.address, amount, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + false, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + deployer.address, + destinationNetwork, + destinationAddress, + amount, + metadata, + 1 + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + expect(mainnetExitRoot).to.be.equal(mainnetExitRoot); + + // Update global exit root + await sovereignChainBridgeContract.updateGlobalExitRoot(); + + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(2); + expect(mainnetExitRoot).to.not.be.equal(rootJSSovereignChain); + + // Just to have the metric of a low cost bridge Asset + const tokenAddress2 = WETHToken.target; // Ether + const amount2 = ethers.parseEther("10"); + await WETHToken.connect(bridgeMock).mint(deployer.address, amount2, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount2, + tokenAddress2, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + 0, // weth bridge + ethers.ZeroAddress, + destinationNetwork, + destinationAddress, + amount2, + "0x", + 2 + ) + .to.emit(WETHToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount2); + }); + + it("should claim Gas tokens from SovereignChain to SovereignChain", async () => { + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = acc1.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + const indexRollup = 5; + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + if (i == indexRollup) { + merkleTreeRollup.add(rootLocalRollup); + } else { + merkleTreeRollup.add(ethers.toBeHex(ethers.toQuantity(ethers.randomBytes(32)), 32)); + } + } + const rootRollup = merkleTreeRollup.getRoot(); + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRoot.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRoot, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const sovereignChainExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(sovereignChainExitRootSC).to.be.equal(rootRollup); + const mainnetExitRootSC = ethers.ZeroHash; + expect(mainnetExitRootSC).to.be.equal(mainnetExitRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rootRollup); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof rollup + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + /* + * claim + * Can't claim without native (ether) + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + rootLocalRollup, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.reverted; + + await setBalance(sovereignChainBridgeContract.target as any, amount); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + const initialBalance = await ethers.provider.getBalance(sovereignChainBridgeContract.target); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + { + gasPrice: 0, + } + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(initialBalance - amount).to.be.equal( + await ethers.provider.getBalance(sovereignChainBridgeContract.target) + ); + }); + + it("should claim tokens from SovereignChain to SovereignChain2", async () => { + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + merkleTreeRollup.add(rootLocalRollup); + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRoot.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRoot, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof local + const indexRollup = 5; + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + // claim + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); + const precalculateWrappedErc20 = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + salt, + hashInitCode + ); + const newWrappedToken = tokenWrappedFactory.attach(precalculateWrappedErc20) as TokenWrapped; + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.precalculatedWrapperAddress( + networkIDRollup, + tokenAddress, + tokenName, + tokenSymbol, + decimals + ) + ).to.be.equal(precalculateWrappedErc20); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(sovereignChainBridgeContract, "NewWrappedToken") + .withArgs(originNetwork, tokenAddress, precalculateWrappedErc20, metadata) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + const newTokenInfo = await sovereignChainBridgeContract.wrappedTokenToTokenInfo(precalculateWrappedErc20); + + expect(newTokenInfo.originNetwork).to.be.equal(networkIDRollup); + expect(newTokenInfo.originTokenAddress).to.be.equal(tokenAddress); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + + expect(await sovereignChainBridgeContract.tokenInfoToWrappedToken(salt)).to.be.equal(precalculateWrappedErc20); + + // Check the wrapper info + expect(await newWrappedToken.name()).to.be.equal(tokenName); + expect(await newWrappedToken.symbol()).to.be.equal(tokenSymbol); + expect(await newWrappedToken.decimals()).to.be.equal(decimals); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + + // Claim again the other leaf to mint tokens + const index2 = 1; + const proof2 = merkleTreeLocal.getProofTreeByIndex(index2); + + expect(verifyMerkleProof(leafValue, proof2, index2, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rollupExitRootSC)).to.be.equal(true); + + const globalIndex2 = computeGlobalIndex(index2, indexRollup, false); + await expect( + sovereignChainBridgeContract.claimAsset( + proof2, + proofRollup, + globalIndex2, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex2, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + // Burn Tokens + const depositCount = await sovereignChainBridgeContract.depositCount(); + const wrappedTokenAddress = newWrappedToken.target; + const newDestinationNetwork = networkIDRollup; + + const rollupExitRoot = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + + // create a new deposit + await expect(newWrappedToken.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(newWrappedToken, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + /* + * pre compute root merkle tree in Js + * const height = 32; + */ + const merkleTreeMainnet = new MerkleTreeBridge(height); + // Imporant calcualte leaf with origin token address no wrapped token address + const originTokenAddress = tokenAddress; + const metadataMainnet = metadata; // since the token does not belong to this network + const metadataHashMainnet = ethers.solidityPackedKeccak256(["bytes"], [metadataMainnet]); + + const leafValueMainnet = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + const leafValueMainnetSC = await sovereignChainBridgeContract.getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + + expect(leafValueMainnet).to.be.equal(leafValueMainnetSC); + merkleTreeMainnet.add(leafValueMainnet); + const rootJSMainnet = ethers.ZeroHash; + + // Tokens are burnt + expect(await newWrappedToken.totalSupply()).to.be.equal(amount * 2n); + expect(await newWrappedToken.balanceOf(destinationAddress)).to.be.equal(amount * 2n); + await expect( + sovereignChainBridgeContract.bridgeAsset( + newDestinationNetwork, + destinationAddress, + amount, + wrappedTokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataMainnet, + depositCount + ) + .to.emit(newWrappedToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(0); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + + // check merkle proof + const proofMainnet = merkleTreeMainnet.getProofTreeByIndex(0); + const indexMainnet = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValueMainnet, proofMainnet, indexMainnet, rootSCSovereignChain)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof( + leafValueMainnet, + proofMainnet, + indexMainnet, + rootSCSovereignChain + ) + ).to.be.equal(true); + }); + + it("should PolygonZkEVMBridge and sync the current root with events", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // gasToken + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + // create 3 new deposit + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + 1n + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + 2n + ); + + // Prepare merkle tree + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + + // Get the deposit's events + const filter = sovereignChainBridgeContract.filters.BridgeEvent( + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined + ); + const events = await sovereignChainBridgeContract.queryFilter(filter, 0, "latest"); + events.forEach((e) => { + const {args} = e; + const leafValue = getLeafValue( + args.leafType, + args.originNetwork, + args.originAddress, + args.destinationNetwork, + args.destinationAddress, + args.amount, + ethers.solidityPackedKeccak256(["bytes"], [args.metadata]) + ); + merkleTree.add(leafValue); + }); + + // Check merkle root with SC + const rootSC = await sovereignChainBridgeContract.getRoot(); + const rootJS = merkleTree.getRoot(); + + expect(rootSC).to.be.equal(rootJS); + }); + + it("should claim testing all the asserts", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + const globalIndex = computeGlobalIndex(index, index, false); + // Can't claim without tokens + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.reverted; + + await setBalance(sovereignChainBridgeContract.target as any, amount); + + // Check GlobalExitRoot invalid assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + mainnetExitRoot, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "GlobalExitRootInvalid"); + + // Check Invalid smt proof assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex + 1n, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount); + + // Check Already claimed_claim + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim ether", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + // claim weth + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(WETHToken, "Transfer") + .withArgs(ethers.ZeroAddress, deployer.address, amount); + + // Check balances after claim + expect(await WETHToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await WETHToken.totalSupply()).to.be.equal(amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim message", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + /* + * claim + * Can't claim a message as an assets + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + const balanceDeployer = await ethers.provider.getBalance(deployer.address); + + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(WETHToken, "Transfer") + .withArgs(ethers.ZeroAddress, deployer.address, amount); + + // Check balances after claim + expect(await WETHToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await WETHToken.totalSupply()).to.be.equal(amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); +}); diff --git a/test/contractsv2/BridgeL2SovereignChain.test.ts b/test/contractsv2/BridgeL2SovereignChain.test.ts new file mode 100644 index 000000000..fcf46b730 --- /dev/null +++ b/test/contractsv2/BridgeL2SovereignChain.test.ts @@ -0,0 +1,2201 @@ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + ERC20PermitMock, + GlobalExitRootManagerL2SovereignChain, + BridgeL2SovereignChain, + TokenWrapped, +} from "../../typechain-types"; +import {processorUtils, contractUtils, MTBridge, mtBridgeUtils} from "@0xpolygonhermez/zkevm-commonjs"; +const MerkleTreeBridge = MTBridge; +const {verifyMerkleProof, getLeafValue} = mtBridgeUtils; + +function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { + return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); +} +const _GLOBAL_INDEX_MAINNET_FLAG = 2n ** 64n; + +function computeGlobalIndex(indexLocal: any, indexRollup: any, isMainnet: Boolean) { + if (isMainnet === true) { + return BigInt(indexLocal) + _GLOBAL_INDEX_MAINNET_FLAG; + } else { + return BigInt(indexLocal) + BigInt(indexRollup) * 2n ** 32n; + } +} + +describe("BridgeL2SovereignChain Contract", () => { + upgrades.silenceWarnings(); + + let sovereignChainBridgeContract: BridgeL2SovereignChain; + let polTokenContract: ERC20PermitMock; + let sovereignChainGlobalExitRootContract: GlobalExitRootManagerL2SovereignChain; + + let deployer: any; + let rollupManager: any; + let bridgeManager: any; + let acc1: any; + + const tokenName = "Matic Token"; + const tokenSymbol = "MATIC"; + const decimals = 18; + const tokenInitialBalance = ethers.parseEther("20000000"); + const metadataToken = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [tokenName, tokenSymbol, decimals] + ); + const networkIDMainnet = 0; + const networkIDRollup = 1; + const networkIDRollup2 = 2; + + const LEAF_TYPE_ASSET = 0; + const LEAF_TYPE_MESSAGE = 1; + + beforeEach("Deploy contracts", async () => { + // load signers + [deployer, rollupManager, acc1, bridgeManager] = await ethers.getSigners(); + // Set trusted sequencer as coinbase for sovereign chains + await ethers.provider.send("hardhat_setCoinbase", [deployer.address]); + // deploy BridgeL2SovereignChain + const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) as unknown as BridgeL2SovereignChain; + + // deploy global exit root manager + const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory( + "GlobalExitRootManagerL2SovereignChain" + ); + sovereignChainGlobalExitRootContract = (await upgrades.deployProxy( + PolygonZkEVMGlobalExitRootFactory, + [deployer.address], // Initializer params + { + initializer: "initialize", // initializer function name + constructorArgs: [sovereignChainBridgeContract.target], // Constructor arguments + unsafeAllow: ["constructor", "state-variable-immutable"], + } + )) as unknown as GlobalExitRootManagerL2SovereignChain; + + // cannot initialize bridgeV2 initializer from Sovereign bridge + await expect( + sovereignChainBridgeContract.initialize( + networkIDMainnet, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + "0x" + ) + ).to.revertedWithCustomError(sovereignChainBridgeContract, "InvalidInitializeFunction"); + + await sovereignChainBridgeContract.initialize( + networkIDRollup2, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + "0x", + ethers.Typed.address(bridgeManager), + ethers.ZeroAddress, + false + ); + + // deploy token + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + }); + + it("should check the initialize function", async () => { + // deploy PolygonZkEVMBridge + const sovereignChainBridgeContract = await ethers.getContractFactory("BridgeL2SovereignChain"); + const bridge = await upgrades.deployProxy(sovereignChainBridgeContract, [], { + initializer: false, + unsafeAllow: ["constructor"], + }); + + // Gas token network should be zero if gas token address is zero + await expect( + bridge.initialize( + networkIDRollup2, + ethers.ZeroAddress, // zero for ether + 1, // not zero, revert + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + ethers.ZeroAddress, + false + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "GasTokenNetworkMustBeZeroOnEther"); + + // _sovereignWETHAddress should be zero and _sovereignWETHAddressIsNotMintable should be false for native wethGasTokenNetworks + await expect( + bridge.initialize( + networkIDRollup2, + ethers.ZeroAddress, // zero for ether + 0, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + bridge.target, // Not zero, revert + false + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSovereignWETHAddressParams"); + + await expect( + bridge.initialize( + networkIDRollup2, + ethers.ZeroAddress, // zero for ether + 0, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + ethers.ZeroAddress, + true // Not false, revert + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSovereignWETHAddressParams"); + }); + + it("Migrate non mintable tokens", async () => { + // Deploy token1 + const tokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const iBalance = ethers.parseEther("20000000"); + const migrationAmount = ethers.parseEther("10"); + const networkIDRollup1 = 1; + const legacyToken = await tokenFactory.deploy(tokenName, tokenSymbol, deployer.address, iBalance); + // Send legacy tokens to user + await legacyToken.transfer(acc1.address, migrationAmount); + expect(await legacyToken.balanceOf(acc1.address)).to.be.equal(migrationAmount); + // Approve token transfer to bridge + await legacyToken.connect(acc1).approve(sovereignChainBridgeContract.target, migrationAmount); + + // Try migrate token that is not mapped + await expect( + sovereignChainBridgeContract.connect(acc1).migrateLegacyToken(legacyToken.target, migrationAmount) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotMapped"); + + // Make first remapping + await sovereignChainBridgeContract + .connect(bridgeManager) + .setSovereignTokenAddress(networkIDRollup1, polTokenContract.target, legacyToken.target, true); + // Deploy token 2 + const updatedToken = await tokenFactory.deploy(tokenName, tokenSymbol, deployer.address, iBalance); + // Send legacy tokens to bridge + await updatedToken.transfer(sovereignChainBridgeContract.target, migrationAmount); + expect(await updatedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(migrationAmount); + // Make second remapping + await sovereignChainBridgeContract + .connect(bridgeManager) + .setSovereignTokenAddress(networkIDRollup1, polTokenContract.target, updatedToken.target, true); + + // Try migrate a token already updated + await expect( + sovereignChainBridgeContract.connect(acc1).migrateLegacyToken(updatedToken.target, migrationAmount) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenAlreadyUpdated"); + + // Migrate tokens + await sovereignChainBridgeContract.connect(acc1).migrateLegacyToken(legacyToken.target, migrationAmount); + expect(await legacyToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(migrationAmount); + expect(await legacyToken.balanceOf(acc1.address)).to.be.equal(0n); + expect(await updatedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(0n); + expect(await updatedToken.balanceOf(acc1.address)).to.be.equal(migrationAmount); + }); + + it("should Sovereign Chain bridge a remapped asset not mintable and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // deploy sovereign + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const sovereignToken = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const sovereignToken2 = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const sovereignToken3 = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const sovereignToken4 = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const tokenAddress2 = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const balanceDeployer = await sovereignToken.balanceOf(deployer.address); + const balanceBridge = await sovereignToken.balanceOf(sovereignChainBridgeContract.target); + // Remap asset + // Remap not mintable token + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setSovereignTokenAddress(networkIDRollup, tokenAddress, sovereignToken.target, true) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress, sovereignToken.target, true); + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + // Check insufficient allowance + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + sovereignToken.target, + true, + "0x" + ) + ).to.be.revertedWith("ERC20: insufficient allowance"); + // create a new deposit + await expect(sovereignToken.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(sovereignToken, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + sovereignToken.target, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + networkIDRollup, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + // Check updated exit root + expect(await sovereignChainGlobalExitRootContract.lastRollupExitRoot()).to.be.equal(rootJSMainnet); + expect(await sovereignToken.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await sovereignToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(balanceBridge + amount); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + + // Try to insert global exit root with non coinbase + await expect( + sovereignChainGlobalExitRootContract.connect(acc1).insertGlobalExitRoot(computedGlobalExitRoot) + ).to.be.revertedWithCustomError(sovereignChainGlobalExitRootContract, "OnlyAggOracleOrCoinbase"); + + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.be.eq(1); + + expect(await sovereignChainGlobalExitRootContract.insertedGERCount()).to.be.eq(1); + + // Trigger NotEnoughGlobalExitRootsInserted + await expect( + sovereignChainGlobalExitRootContract.removeLastGlobalExitRoots([ + computedGlobalExitRoot, + computedGlobalExitRoot, + ]) + ).to.revertedWithCustomError(sovereignChainGlobalExitRootContract, "NotEnoughGlobalExitRootsInserted"); + + // Trigger NotLastInsertedGlobalExitRoot + await expect( + sovereignChainGlobalExitRootContract.removeLastGlobalExitRoots([metadataHash]) + ).to.revertedWithCustomError(sovereignChainGlobalExitRootContract, "NotLastInsertedGlobalExitRoot"); + + // Remove global exit root + expect(await sovereignChainGlobalExitRootContract.removeLastGlobalExitRoots([computedGlobalExitRoot])) + .to.emit(sovereignChainGlobalExitRootContract, "RemoveGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.be.eq(0); + + expect(await sovereignChainGlobalExitRootContract.insertedGERCount()).to.be.eq(0); + + // Insert global exit root again + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // Remove unmapped sovereign token address, should revert + await expect( + sovereignChainBridgeContract.connect(bridgeManager).removeSovereignTokenAddress(tokenAddress) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotMapped"); + // Remove not updated sovereign token address, should revert + await expect( + sovereignChainBridgeContract.connect(bridgeManager).removeSovereignTokenAddress(sovereignToken.target) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotMapped"); + + // Remove updated sovereign token address + // Remap token a second time to support removal function + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setSovereignTokenAddress(networkIDRollup, tokenAddress, sovereignToken2.target, true) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress, sovereignToken2.target, true); + await expect( + sovereignChainBridgeContract.connect(bridgeManager).removeSovereignTokenAddress(sovereignToken.target) + ) + .to.emit(sovereignChainBridgeContract, "RemoveSovereignTokenAddress") + .withArgs(sovereignToken.target); + // Remap sovereign address with multiCall + const originNetworksArray = [networkIDRollup, networkIDRollup]; + const originTokenAddressesArray = [tokenAddress, tokenAddress2.target]; + const sovereignTokenAddressesArray = [sovereignToken3.target, sovereignToken4.target]; + const isNotMintableArray = [true, false]; + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setMultipleSovereignTokenAddress( + originNetworksArray, + originTokenAddressesArray, + sovereignTokenAddressesArray, + isNotMintableArray + ) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress, sovereignToken3.target, true) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress2.target, sovereignToken4.target, false); + }); + + it("should Sovereign Chain bridge a remapped asset mintable and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // deploy sovereign + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const sovereignToken = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + + // Remap asset + // Trigger requires + // only bridge manager + await expect( + sovereignChainBridgeContract + .connect(rollupManager) + .setSovereignTokenAddress(networkIDMainnet, tokenAddress, sovereignToken.target, false) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyBridgeManager"); + // Set rollupManager as bridge manager + await expect(sovereignChainBridgeContract.connect(bridgeManager).setBridgeManager(rollupManager.address)) + .to.emit(sovereignChainBridgeContract, "SetBridgeManager") + .withArgs(rollupManager.address); + + // invalid token address + await expect( + sovereignChainBridgeContract + .connect(rollupManager) + .setSovereignTokenAddress(networkIDMainnet, ethers.ZeroAddress, sovereignToken.target, false) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidZeroAddress"); + // Invalid origin network + await expect( + sovereignChainBridgeContract + .connect(rollupManager) + .setSovereignTokenAddress(networkIDRollup2, tokenAddress, sovereignToken.target, false) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OriginNetworkInvalid"); + await expect( + sovereignChainBridgeContract + .connect(rollupManager) + .setSovereignTokenAddress(networkIDRollup, tokenAddress, sovereignToken.target, false) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress, sovereignToken.target, false); + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + // Check updated exit root + expect(await sovereignChainGlobalExitRootContract.lastRollupExitRoot()).to.be.equal(rootJSMainnet); + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + }); + + it("should check the initialize parameters", async () => { + expect(await sovereignChainBridgeContract.globalExitRootManager()).to.be.equal( + sovereignChainGlobalExitRootContract.target + ); + expect(await sovereignChainBridgeContract.networkID()).to.be.equal(networkIDRollup2); + expect(await sovereignChainBridgeContract.polygonRollupManager()).to.be.equal(rollupManager.address); + + // cannot initialize again + await expect( + sovereignChainBridgeContract.initialize( + networkIDMainnet, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + "0x", + ethers.Typed.address(bridgeManager), + ethers.ZeroAddress, + false + ) + ).to.be.revertedWith("Initializable: contract is already initialized"); + + await expect(sovereignChainGlobalExitRootContract.initialize(ethers.ZeroAddress)).to.be.revertedWith( + "Initializable: contract is already initialized" + ); + }); + + it("should check bridgeMessageWETH reverts", async () => { + await expect( + sovereignChainBridgeContract.bridgeMessageWETH(networkIDMainnet, deployer.address, 0, true, "0x") + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NativeTokenIsEther"); + }); + + it("should Sovereign Chain bridge asset and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: 1} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "MsgValueNotZero"); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + // Check updated exit root + expect(await sovereignChainGlobalExitRootContract.lastRollupExitRoot()).to.be.equal(rootJSMainnet); + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + }); + + it("should message at Sovereign chain and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const originAddress = deployer.address; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeMessage(networkIDRollup2, destinationAddress, true, "0x") + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, { + value: amount, + }) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + }); + + it("should bridge asset and message to sovereign chain to check global exit root updates", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(0); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // Update global exit root + await sovereignChainBridgeContract.updateGlobalExitRoot(); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // bridge message + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, false, metadata, { + value: amount, + }) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + deployer.address, + destinationNetwork, + destinationAddress, + amount, + metadata, + 1 + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // Update global exit root + await sovereignChainBridgeContract.updateGlobalExitRoot(); + + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(2); + expect(await sovereignChainGlobalExitRootContract.lastRollupExitRoot()).to.not.be.equal(rootJSMainnet); + + // Just to have the metric of a low cost bridge Asset + const tokenAddress2 = ethers.ZeroAddress; // Ether + const amount2 = ethers.parseEther("10"); + await sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount2, + tokenAddress2, + false, + "0x", + {value: amount2} + ); + }); + + it("should claim tokens from Mainnet to Mainnet", async () => { + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = acc1.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + const indexRollup = 5; + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + if (i == indexRollup) { + merkleTreeRollup.add(rootLocalRollup); + } else { + merkleTreeRollup.add(ethers.toBeHex(ethers.toQuantity(ethers.randomBytes(32)), 32)); + } + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // check merkle proof + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof rollup + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + /* + * claim + * Can't claim without tokens + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + Number(globalIndex), + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWith("ERC20: transfer amount exceeds balance"); + + // transfer tokens, then claim + await expect(polTokenContract.transfer(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Transfer") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(polTokenContract, "Transfer") + .withArgs(sovereignChainBridgeContract.target, acc1.address, amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + }); + + it("should claim tokens from Rollup to Mainnet", async () => { + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + merkleTreeRollup.add(rootLocalRollup); + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof local + const indexRollup = 5; + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + // claim + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); + const precalculateWrappedErc20 = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + salt, + hashInitCode + ); + const newWrappedToken = tokenWrappedFactory.attach(precalculateWrappedErc20) as TokenWrapped; + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.precalculatedWrapperAddress( + networkIDRollup, + tokenAddress, + tokenName, + tokenSymbol, + decimals + ) + ).to.be.equal(precalculateWrappedErc20); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(sovereignChainBridgeContract, "NewWrappedToken") + .withArgs(originNetwork, tokenAddress, precalculateWrappedErc20, metadata) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + const newTokenInfo = await sovereignChainBridgeContract.wrappedTokenToTokenInfo(precalculateWrappedErc20); + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.calculateTokenWrapperAddress( + networkIDRollup, + tokenAddress, + precalculateWrappedErc20 + ) + ).to.be.equal(precalculateWrappedErc20); + + expect(newTokenInfo.originNetwork).to.be.equal(networkIDRollup); + expect(newTokenInfo.originTokenAddress).to.be.equal(tokenAddress); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + + expect(await sovereignChainBridgeContract.tokenInfoToWrappedToken(salt)).to.be.equal(precalculateWrappedErc20); + + // Check the wrapper info + expect(await newWrappedToken.name()).to.be.equal(tokenName); + expect(await newWrappedToken.symbol()).to.be.equal(tokenSymbol); + expect(await newWrappedToken.decimals()).to.be.equal(decimals); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + + // Claim again the other leaf to mint tokens + const index2 = 1; + const proof2 = merkleTreeLocal.getProofTreeByIndex(index2); + + expect(verifyMerkleProof(leafValue, proof2, index2, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rollupExitRootSC)).to.be.equal(true); + + const globalIndex2 = computeGlobalIndex(index2, indexRollup, false); + await expect( + sovereignChainBridgeContract.claimAsset( + proof2, + proofRollup, + globalIndex2, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex2, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + // Burn Tokens + const depositCount = await sovereignChainBridgeContract.depositCount(); + const wrappedTokenAddress = newWrappedToken.target; + const newDestinationNetwork = networkIDRollup; + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(newWrappedToken.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(newWrappedToken, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + /* + * pre compute root merkle tree in Js + * const height = 32; + */ + const merkleTreeMainnet = new MerkleTreeBridge(height); + // Imporant calcualte leaf with origin token address no wrapped token address + const originTokenAddress = tokenAddress; + const metadataMainnet = metadata; // since the token does not belong to this network + const metadataHashMainnet = ethers.solidityPackedKeccak256(["bytes"], [metadataMainnet]); + + const leafValueMainnet = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + const leafValueMainnetSC = await sovereignChainBridgeContract.getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + + expect(leafValueMainnet).to.be.equal(leafValueMainnetSC); + merkleTreeMainnet.add(leafValueMainnet); + const rootJSMainnet = merkleTreeMainnet.getRoot(); + + // Tokens are burnt + expect(await newWrappedToken.totalSupply()).to.be.equal(amount * 2n); + expect(await newWrappedToken.balanceOf(destinationAddress)).to.be.equal(amount * 2n); + await expect( + sovereignChainBridgeContract.bridgeAsset( + newDestinationNetwork, + destinationAddress, + amount, + wrappedTokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataMainnet, + depositCount + ) + .to.emit(newWrappedToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(0); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proofMainnet = merkleTreeMainnet.getProofTreeByIndex(0); + const indexMainnet = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValueMainnet, proofMainnet, indexMainnet, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof( + leafValueMainnet, + proofMainnet, + indexMainnet, + rootSCMainnet + ) + ).to.be.equal(true); + + const computedGlobalExitRoot2 = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot2)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot2)).to.not.be.eq(0); + + // Insert an already inserted GER + await expect( + sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot2) + ).to.revertedWithCustomError(sovereignChainGlobalExitRootContract, "GlobalExitRootAlreadySet"); + }); + it("should claim tokens from Rollup to Mainnet, failing deploy wrapped", async () => { + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = ethers.hexlify(ethers.randomBytes(40)); + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + merkleTreeRollup.add(rootLocalRollup); + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof local + const indexRollup = 5; + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + // claim + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); + const precalculateWrappedErc20 = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + salt, + hashInitCode + ); + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.precalculatedWrapperAddress( + networkIDRollup, + tokenAddress, + tokenName, + tokenSymbol, + decimals + ) + ).to.be.equal(precalculateWrappedErc20); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "FailedTokenWrappedDeployment"); + }); + it("should sovereignChainBridge and sync the current root with events", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // Ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = "0x"; // since is ether does not have metadata + + // create 3 new deposit + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + 1n + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + 2n + ); + + // Prepare merkle tree + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + + // Get the deposit's events + const filter = sovereignChainBridgeContract.filters.BridgeEvent( + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined + ); + const events = await sovereignChainBridgeContract.queryFilter(filter, 0, "latest"); + events.forEach((e) => { + const {args} = e; + const leafValue = getLeafValue( + args.leafType, + args.originNetwork, + args.originAddress, + args.destinationNetwork, + args.destinationAddress, + args.amount, + ethers.solidityPackedKeccak256(["bytes"], [args.metadata]) + ); + merkleTree.add(leafValue); + }); + + // Check merkle root with SC + const rootSC = await sovereignChainBridgeContract.getRoot(); + const rootJS = merkleTree.getRoot(); + + expect(rootSC).to.be.equal(rootJS); + }); + + it("should claim testing all the asserts", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + const globalIndex = computeGlobalIndex(index, index, false); + // Can't claim without tokens + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWith("ERC20: transfer amount exceeds balance"); + + // transfer tokens, then claim + await expect(polTokenContract.transfer(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Transfer") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // Check GlobalExitRoot invalid assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + mainnetExitRoot, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "GlobalExitRootInvalid"); + + // Check Invalid smt proof assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex + 1n, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(polTokenContract, "Transfer") + .withArgs(sovereignChainBridgeContract.target, deployer.address, amount); + + // Check Already claimed_claim + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim ether", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + /* + * claim + * Can't claim without ether + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "EtherTransferFailed"); + + const balanceDeployer = await ethers.provider.getBalance(deployer.address); + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.bridgeAsset( + networkIDRollup2, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + // This is used just to pay ether to the SovereignChain smart contract and be able to claim it afterwards. + expect( + await sovereignChainBridgeContract.bridgeAsset( + networkIDRollup, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ); + + // Check balances before claim + expect(await ethers.provider.getBalance(sovereignChainBridgeContract.target)).to.be.equal(amount); + expect(await ethers.provider.getBalance(deployer.address)).to.be.lte(balanceDeployer - amount); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount); + + // Check balances after claim + expect(await ethers.provider.getBalance(sovereignChainBridgeContract.target)).to.be.equal( + ethers.parseEther("0") + ); + expect(await ethers.provider.getBalance(deployer.address)).to.be.lte(balanceDeployer); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim message", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + /* + * claim + * Can't claim a message as an assets + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + /* + * claim + * Can't claim invalid destination network + */ + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + networkIDRollup, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + /* + * claim + * Can't claim without ether + */ + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "MessageFailed"); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + networkIDRollup, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + const balanceDeployer = await ethers.provider.getBalance(deployer.address); + /* + * Create a deposit to add ether to the SovereignChainBridge + * Check deposit amount ether asserts + */ + await expect( + sovereignChainBridgeContract.bridgeAsset( + networkIDRollup, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: ethers.parseEther("100")} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AmountDoesNotMatchMsgValue"); + + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.bridgeAsset( + networkIDRollup2, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + // This is used just to pay ether to the SovereignChainBridge smart contract and be able to claim it afterwards. + expect( + await sovereignChainBridgeContract.bridgeAsset( + networkIDRollup, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ); + + // Check balances before claim + expect(await ethers.provider.getBalance(sovereignChainBridgeContract.target)).to.be.equal(amount); + expect(await ethers.provider.getBalance(deployer.address)).to.be.lte(balanceDeployer - amount); + + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount); + + // Check balances after claim + expect(await ethers.provider.getBalance(sovereignChainBridgeContract.target)).to.be.equal( + ethers.parseEther("0") + ); + expect(await ethers.provider.getBalance(deployer.address)).to.be.lte(balanceDeployer); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should test emergency state", async () => { + await expect(sovereignChainBridgeContract.activateEmergencyState()).to.be.revertedWithCustomError( + sovereignChainBridgeContract, + "OnlyRollupManager" + ); + + await expect(sovereignChainBridgeContract.connect(rollupManager).activateEmergencyState()).to.emit( + sovereignChainBridgeContract, + "EmergencyStateActivated" + ); + + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); + + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, "0x") + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH(destinationNetwork, destinationAddress, amount, true, "0x") + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); + + const mockMerkleProof = new Array(32).fill(ethers.ZeroHash) as any; + await expect( + sovereignChainBridgeContract.claimAsset( + mockMerkleProof, + mockMerkleProof, + ethers.ZeroHash, + ethers.ZeroHash, + ethers.ZeroHash, + 0, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); + + await expect( + sovereignChainBridgeContract.claimMessage( + mockMerkleProof, + mockMerkleProof, + ethers.ZeroHash, + ethers.ZeroHash, + ethers.ZeroHash, + 0, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); + }); +}); From a61242007ef1878ea47c2e396bc2d9d7f6ca6ef3 Mon Sep 17 00:00:00 2001 From: krlosMata Date: Fri, 11 Oct 2024 15:48:02 +0200 Subject: [PATCH 2/8] finish injected batch data for pessimisic consensus --- deployment/v2/4_createRollup.ts | 63 +- package-lock.json | 3145 ++++++++++++++++--------------- package.json | 2 +- 3 files changed, 1697 insertions(+), 1513 deletions(-) diff --git a/deployment/v2/4_createRollup.ts b/deployment/v2/4_createRollup.ts index fa06e8b4b..b71de5f00 100644 --- a/deployment/v2/4_createRollup.ts +++ b/deployment/v2/4_createRollup.ts @@ -11,7 +11,7 @@ import {HardhatEthersSigner} from "@nomicfoundation/hardhat-ethers/signers"; const {create2Deployment} = require("../helpers/deployment-helpers"); const pathGenesis = path.join(__dirname, "./genesis.json"); -import {processorUtils} from "@0xpolygonhermez/zkevm-commonjs"; +import {processorUtils, Constants} from "@0xpolygonhermez/zkevm-commonjs"; const createRollupParameters = require("./create_rollup_parameters.json"); const genesis = require("./genesis.json"); @@ -25,6 +25,7 @@ import { PolygonZkEVMEtrog, PolygonZkEVMBridgeV2, PolygonValidiumEtrog, + PolygonPessimisticConsensus, } from "../../typechain-types"; async function main() { @@ -347,34 +348,55 @@ async function main() { let batchData; if (consensusContract === "PolygonPessimisticConsensus") { + // Add the first batch of the created rollup + const newZKEVMContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonPessimisticConsensus; + // Get last GER const lastGER = await globalExitRootManagerContract.getLastGlobalExitRoot(); - const lastBlock = await ethers.provider.getBlock("latest"); - const timestamp = lastBlock?.timestamp; - const uTx = await polygonZkEVMBridgeContract.initialize.populateTransaction( + + const dataInjectedTx = await polygonZkEVMBridgeContract.interface.encodeFunctionData("initialize", [ rollupID, gasTokenAddress, gasTokenNetwork, - globalExitRootManagerContract.target, - rollupManagerContract.target, - gasTokenMetadata as any - ); - uTx.gasPrice = BigInt(0); - uTx.gasLimit = BigInt(3000000); // 30M of gas - uTx.chainId = chainID; - uTx.type = 0; - //uTx.type = 1; - const signer = ethers.HDNodeWallet.fromMnemonic( - ethers.Mnemonic.fromPhrase("test test test test test test test test test test test junk"), - "m/44'/60'/0'/0/0" - ).connect(currentProvider); - const signedTx = await signer.signTransaction(uTx); - const customData = processorUtils.rawTxToCustomRawTx(signedTx); + Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2, // Global exit root address on L2 + ethers.ZeroAddress, // Rollup manager on L2 does not exist + gasTokenMetadata as any, + ]); + + // check maximum length is 65535 + if ((dataInjectedTx.length - 2) / 2 > 0xffff) { + // throw error + throw new Error(`HugeTokenMetadataNotSupported`); + } + + const injectedTx = { + type: 0, // force ethers to parse it as a legacy transaction + chainId: 0, // force ethers to parse it as a pre-EIP155 transaction + to: await newZKEVMContract.bridgeAddress(), + value: 0, + gasPrice: 0, + gasLimit: 30000000, + nonce: 0, + data: dataInjectedTx, + signature: { + v: "0x1b", + r: "0x00000000000000000000000000000000000000000000000000000005ca1ab1e0", + s: "0x000000000000000000000000000000000000000000000000000000005ca1ab1e", + }, + }; + + // serialize transactions + const txObject = ethers.Transaction.from(injectedTx); + + const customData = processorUtils.rawTxToCustomRawTx(txObject.serialized); batchData = { batchL2Data: customData, globalExitRoot: lastGER, - timestamp: timestamp, + timestamp: blockDeploymentRollup.timestamp, sequencer: trustedSequencer, + l1BlockNumber: blockDeploymentRollup.number, + l1BlockHash: blockDeploymentRollup.hash, + l1ParentHash: blockDeploymentRollup.parentHash, }; } else { // Add the first batch of the created rollup @@ -405,4 +427,3 @@ main().catch((e) => { console.error(e); process.exit(1); }); - diff --git a/package-lock.json b/package-lock.json index 3361ba818..9f3770680 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.0.0", "license": "pending", "devDependencies": { - "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#main", + "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v8.0.0-fork.12", "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@openzeppelin/contracts": "4.8.2", "@openzeppelin/contracts-upgradeable": "4.8.2", @@ -26,21 +26,21 @@ "hardhat": "^2.22.3", "hardhat-dependency-compiler": "^1.1.3", "prettier": "^2.8.8", - "prettier-plugin-solidity": "^1.1.3", + "prettier-plugin-solidity": "^1.4.1", "solc-0.8": "npm:solc@0.8.20", "solidity-docgen": "^0.5.17" } }, "node_modules/@0xpolygonhermez/zkevm-commonjs": { - "version": "2.0.0", - "resolved": "git+ssh://git@github.com/0xPolygonHermez/zkevm-commonjs.git#06a731c47a1c1642b34aa4c9a496e61e017f8b47", + "version": "5.0.0", + "resolved": "git+ssh://git@github.com/0xPolygonHermez/zkevm-commonjs.git#bb0e77e9158a0fc3d06eb5de53b458bb87f77bc7", "dev": true, "license": "pending", "dependencies": { "@ethereumjs/block": "^3.6.2", "@ethereumjs/tx": "^3.4.0", "@polygon-hermez/common": "2.6.4", - "@polygon-hermez/vm": "5.7.36", + "@polygon-hermez/vm": "6.0.13", "ethereumjs-util": "^7.1.4", "ethers": "^5.5.4", "ffjavascript": "^0.2.55", @@ -96,19 +96,10 @@ "@ethersproject/wordlists": "5.7.0" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", "dev": true, "peer": true }, @@ -135,22 +126,22 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.468.0.tgz", - "integrity": "sha512-rx/9uHI4inRbp2tw3Y4Ih4PNZkVj32h7WneSg3MVgVjAoVD5Zti9KhS5hkvsBxfgmQmg0AQbE+b1sy5WGAgntA==", + "version": "3.664.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.664.0.tgz", + "integrity": "sha512-+GtXktvVgpreM2b+NJL9OqZGsOzHwlCUrO8jgQUvH/yA6Kd8QO2YFhQCp0C9sSzTteZJVqGBu8E0CQurxJHPbw==", "dev": true, "dependencies": { - "@smithy/types": "^2.7.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.5.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/types/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/util-utf8-browser": { @@ -163,9 +154,9 @@ } }, "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@cspotcode/source-map-support": { @@ -285,6 +276,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -418,18 +410,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", - "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -449,10 +441,32 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", - "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -993,21 +1007,21 @@ } }, "node_modules/@ethereumjs/util/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, "dependencies": { - "@noble/hashes": "1.3.1" + "@noble/hashes": "1.4.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, "engines": { "node": ">= 16" @@ -1017,15 +1031,15 @@ } }, "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", - "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "dev": true, "dependencies": { - "@noble/curves": "1.1.0", - "@noble/hashes": "1.3.1", - "@scure/bip32": "1.3.1", - "@scure/bip39": "1.2.1" + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" } }, "node_modules/@ethersproject/abi": { @@ -1757,28 +1771,51 @@ } }, "node_modules/@fastify/busboy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", - "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, "engines": { "node": ">=14" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -1793,24 +1830,25 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { @@ -1887,6 +1925,7 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", "dev": true, + "peer": true, "engines": { "node": ">= 16" }, @@ -1942,81 +1981,81 @@ } }, "node_modules/@nomicfoundation/edr": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.8.tgz", - "integrity": "sha512-u2UJ5QpznSHVkZRh6ePWoeVb6kmPrrqh08gCnZ9FHlJV9CITqlrTQHJkacd+INH31jx88pTAJnxePE4XAiH5qg==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.6.3.tgz", + "integrity": "sha512-hThe5ORR75WFYTXKL0K2AyLDxkTMrG+VQ1yL9BhQYsuh3OIH+3yNDxMz2LjfvrpOrMmJ4kk5NKdFewpqDojjXQ==", "dev": true, "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.3.8", - "@nomicfoundation/edr-darwin-x64": "0.3.8", - "@nomicfoundation/edr-linux-arm64-gnu": "0.3.8", - "@nomicfoundation/edr-linux-arm64-musl": "0.3.8", - "@nomicfoundation/edr-linux-x64-gnu": "0.3.8", - "@nomicfoundation/edr-linux-x64-musl": "0.3.8", - "@nomicfoundation/edr-win32-x64-msvc": "0.3.8" + "@nomicfoundation/edr-darwin-arm64": "0.6.3", + "@nomicfoundation/edr-darwin-x64": "0.6.3", + "@nomicfoundation/edr-linux-arm64-gnu": "0.6.3", + "@nomicfoundation/edr-linux-arm64-musl": "0.6.3", + "@nomicfoundation/edr-linux-x64-gnu": "0.6.3", + "@nomicfoundation/edr-linux-x64-musl": "0.6.3", + "@nomicfoundation/edr-win32-x64-msvc": "0.6.3" }, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.8.tgz", - "integrity": "sha512-eB0leCexS8sQEmfyD72cdvLj9djkBzQGP4wSQw6SNf2I4Sw4Cnzb3d45caG2FqFFjbvfqL0t+badUUIceqQuMw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.3.tgz", + "integrity": "sha512-hqtI7tYDqKG5PDmZ//Z65EH5cgH8VL/SAAu50rpHP7WAVfJWkOCcYbecywwF6nhHdonJbRTDGAeG1/+VOy6zew==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.8.tgz", - "integrity": "sha512-JksVCS1N5ClwVF14EvO25HCQ+Laljh/KRfHERMVAC9ZwPbTuAd/9BtKvToCBi29uCHWqsXMI4lxCApYQv2nznw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.3.tgz", + "integrity": "sha512-4fGi79/lyOlRUORhCYsYb3sWqRHuHT7qqzyZfZuNOn8llaxmT1k36xNmvpyg37R8SzjnhT/DzoukSJrs23Ip9Q==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.8.tgz", - "integrity": "sha512-raCE+fOeNXhVBLUo87cgsHSGvYYRB6arih4eG6B9KGACWK5Veebtm9xtKeiD8YCsdUlUfat6F7ibpeNm91fpsA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.3.tgz", + "integrity": "sha512-yFFTvGFMhfAvQ1Z2itUh1jpoUA+mVROyVELcaxjIq8fyg602lQmbS+NXkhQ+oaeDgJ+06mSENrHBg4fcfRf9cw==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.8.tgz", - "integrity": "sha512-PwiDp4wBZWMCIy29eKkv8moTKRrpiSDlrc+GQMSZLhOAm8T33JKKXPwD/2EbplbhCygJDGXZdtEKl9x9PaH66A==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.3.tgz", + "integrity": "sha512-pOKmd0Fa3a6BHg5qbjbl/jMRELVi9oazbfiuU7Bvgn/dpTK+ID3jwT0SXiuC2zxjmPByWgXL6G9XRf5BPAM2rQ==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.8.tgz", - "integrity": "sha512-6AcvA/XKoipGap5jJmQ9Y6yT7Uf39D9lu2hBcDCXnXbMcXaDGw4mn1/L4R63D+9VGZyu1PqlcJixCUZlGGIWlg==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.3.tgz", + "integrity": "sha512-3AUferhkLIXtLV63w5GjpHttzdxZ36i656XMy+pkBZbbiqnzIVeKWg6DJv1A94fQY16gB4gqj9CLq4CWvbNN6w==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.8.tgz", - "integrity": "sha512-cxb0sEmZjlwhYWO28sPsV64VDx31ekskhC1IsDXU1p9ntjHSJRmW4KEIqJ2O3QwJap/kLKfMS6TckvY10gjc6w==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.3.tgz", + "integrity": "sha512-fr6bD872WIBXe9YnTDi0CzYepMcYRgSnkVqn0yK4wRnIvKrloWhxXNVY45GVIl51aNZguBnvoA4WEt6HIazs3A==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.8.tgz", - "integrity": "sha512-yVuVPqRRNLZk7TbBMkKw7lzCvI8XO8fNTPTYxymGadjr9rEGRuNTU1yBXjfJ59I1jJU/X2TSkRk1OFX0P5tpZQ==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.3.tgz", + "integrity": "sha512-sn34MvN1ajw2Oq1+Drpxej78Z0HfIzI4p4WlolupAV9dOZKzp2JAIQeLVfZpjIFbF3zuyxLPP4dUBrQoFPEqhA==", "dev": true, "engines": { "node": ">= 18" @@ -2088,9 +2127,9 @@ } }, "node_modules/@nomicfoundation/hardhat-chai-matchers": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.2.tgz", - "integrity": "sha512-9Wu9mRtkj0U9ohgXYFbB/RQDa+PcEdyBm2suyEtsJf3PqzZEEjLUZgWnMjlFhATMk/fp3BjmnYVPrwl+gr8oEw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.8.tgz", + "integrity": "sha512-Z5PiCXH4xhNLASROlSUOADfhfpfhYO6D7Hn9xp8PddmHey0jq704cr6kfU8TRrQ4PUZbpfsZadPj+pCfZdjPIg==", "dev": true, "peer": true, "dependencies": { @@ -2107,9 +2146,9 @@ } }, "node_modules/@nomicfoundation/hardhat-ethers": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.4.tgz", - "integrity": "sha512-k9qbLoY7qn6C6Y1LI0gk2kyHXil2Tauj4kGzQ8pgxYXIGw8lWn8tuuL72E11CrlKaXRUvOgF0EXrv/msPI2SbA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.8.tgz", + "integrity": "sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==", "dev": true, "peer": true, "dependencies": { @@ -2122,9 +2161,9 @@ } }, "node_modules/@nomicfoundation/hardhat-network-helpers": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.9.tgz", - "integrity": "sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.12.tgz", + "integrity": "sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==", "dev": true, "peer": true, "dependencies": { @@ -2180,185 +2219,193 @@ "hardhat": "^2.0.4" } }, - "node_modules/@nomicfoundation/solidity-analyzer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", - "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", + "node_modules/@nomicfoundation/slang": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang/-/slang-0.17.0.tgz", + "integrity": "sha512-1GlkGRcGpVnjFw9Z1vvDKOKo2mzparFt7qrl2pDxWp+jrVtlvej98yCMX52pVyrYE7ZeOSZFnx/DtsSgoukStQ==", "dev": true, - "engines": { - "node": ">= 12" + "dependencies": { + "@nomicfoundation/slang-darwin-arm64": "0.17.0", + "@nomicfoundation/slang-darwin-x64": "0.17.0", + "@nomicfoundation/slang-linux-arm64-gnu": "0.17.0", + "@nomicfoundation/slang-linux-arm64-musl": "0.17.0", + "@nomicfoundation/slang-linux-x64-gnu": "0.17.0", + "@nomicfoundation/slang-linux-x64-musl": "0.17.0", + "@nomicfoundation/slang-win32-arm64-msvc": "0.17.0", + "@nomicfoundation/slang-win32-ia32-msvc": "0.17.0", + "@nomicfoundation/slang-win32-x64-msvc": "0.17.0" }, - "optionalDependencies": { - "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.1", - "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.1", - "@nomicfoundation/solidity-analyzer-freebsd-x64": "0.1.1", - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.1", - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.1", - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.1", - "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.1", - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": "0.1.1", - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": "0.1.1", - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.1" + "engines": { + "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz", - "integrity": "sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==", - "cpu": [ - "arm64" - ], + "node_modules/@nomicfoundation/slang-darwin-arm64": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-darwin-arm64/-/slang-darwin-arm64-0.17.0.tgz", + "integrity": "sha512-O0q94EUtoWy9A5kOTOa9/khtxXDYnLqmuda9pQELurSiwbQEVCPQL8kb34VbOW+ifdre66JM/05Xw9JWhIZ9sA==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz", - "integrity": "sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==", - "cpu": [ - "x64" - ], + "node_modules/@nomicfoundation/slang-darwin-x64": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-darwin-x64/-/slang-darwin-x64-0.17.0.tgz", + "integrity": "sha512-IaDbHzvT08sBK2HyGzonWhq1uu8IxdjmTqAWHr25Oh/PYnamdi8u4qchZXXYKz/DHLoYN3vIpBXoqLQIomhD/g==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-freebsd-x64": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz", - "integrity": "sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==", - "cpu": [ - "x64" - ], + "node_modules/@nomicfoundation/slang-linux-arm64-gnu": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-linux-arm64-gnu/-/slang-linux-arm64-gnu-0.17.0.tgz", + "integrity": "sha512-Lj4anvOsQZxs1SycG8VyT2Rl2oqIhyLSUCgGepTt3CiJ/bM+8r8bLJIgh8vKkki4BWz49YsYIgaJB2IPv8FFTw==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], "engines": { "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz", - "integrity": "sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==", - "cpu": [ - "arm64" - ], + "node_modules/@nomicfoundation/slang-linux-arm64-musl": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-linux-arm64-musl/-/slang-linux-arm64-musl-0.17.0.tgz", + "integrity": "sha512-/xkTCa9d5SIWUBQE3BmLqDFfJRr4yUBwbl4ynPiGUpRXrD69cs6pWKkwjwz/FdBpXqVo36I+zY95qzoTj/YhOA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz", - "integrity": "sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==", - "cpu": [ - "arm64" - ], + "node_modules/@nomicfoundation/slang-linux-x64-gnu": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-linux-x64-gnu/-/slang-linux-x64-gnu-0.17.0.tgz", + "integrity": "sha512-oe5IO5vntOqYvTd67deCHPIWuSuWm6aYtT2/0Kqz2/VLtGz4ClEulBSRwfnNzBVtw2nksWipE1w8BzhImI7Syg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz", - "integrity": "sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==", - "cpu": [ - "x64" - ], + "node_modules/@nomicfoundation/slang-linux-x64-musl": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-linux-x64-musl/-/slang-linux-x64-musl-0.17.0.tgz", + "integrity": "sha512-PpYCI5K/kgLAMXaPY0V4VST5gCDprEOh7z/47tbI8kJQumI5odjsj/Cs8MpTo7/uRH6flKYbVNgUzcocWVYrAQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz", - "integrity": "sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==", - "cpu": [ - "x64" - ], + "node_modules/@nomicfoundation/slang-win32-arm64-msvc": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-win32-arm64-msvc/-/slang-win32-arm64-msvc-0.17.0.tgz", + "integrity": "sha512-u/Mkf7OjokdBilP7QOJj6QYJU4/mjkbKnTX21wLyCIzeVWS7yafRPYpBycKIBj2pRRZ6ceAY5EqRpb0aiCq+0Q==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-arm64-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz", - "integrity": "sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==", - "cpu": [ - "arm64" - ], + "node_modules/@nomicfoundation/slang-win32-ia32-msvc": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-win32-ia32-msvc/-/slang-win32-ia32-msvc-0.17.0.tgz", + "integrity": "sha512-XJBVQfNnZQUv0tP2JSJ573S+pmgrLWgqSZOGaMllnB/TL1gRci4Z7dYRJUF2s82GlRJE+FHSI2Ro6JISKmlXCg==", "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { "node": ">= 10" } }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-ia32-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz", - "integrity": "sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==", - "cpu": [ - "ia32" - ], + "node_modules/@nomicfoundation/slang-win32-x64-msvc": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang-win32-x64-msvc/-/slang-win32-x64-msvc-0.17.0.tgz", + "integrity": "sha512-zPGsAeiTfqfPNYHD8BfrahQmYzA78ZraoHKTGraq/1xwJwzBK4bu/NtvVA4pJjBV+B4L6DCxVhSbpn40q26JQA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { "node": ">= 10" } }, + "node_modules/@nomicfoundation/solidity-analyzer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz", + "integrity": "sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==", + "dev": true, + "engines": { + "node": ">= 12" + }, + "optionalDependencies": { + "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.2", + "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.2" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz", + "integrity": "sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz", + "integrity": "sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz", + "integrity": "sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz", + "integrity": "sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz", + "integrity": "sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz", + "integrity": "sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz", - "integrity": "sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==", - "cpu": [ - "x64" - ], + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz", + "integrity": "sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==", "dev": true, "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/@oclif/command": { @@ -2382,26 +2429,11 @@ "@oclif/config": "^1" } }, - "node_modules/@oclif/command/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@oclif/command/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -2409,12 +2441,6 @@ "node": ">=10" } }, - "node_modules/@oclif/command/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@oclif/config": { "version": "1.18.17", "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.17.tgz", @@ -2463,15 +2489,15 @@ } }, "node_modules/@oclif/config/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@oclif/core": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-2.15.0.tgz", - "integrity": "sha512-fNEMG5DzJHhYmI3MgpByTvltBOMyFcnRIUMxbiz2ai8rhaYgaTHMG3Q38HcosfIvtw9nCjxpcQtC8MN8QtVCcA==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-2.16.0.tgz", + "integrity": "sha512-dL6atBH0zCZl1A1IXCKJgLPrM/wR7K+Wi401E/IvqsK8m2iCHW+0TEOGrans/cuN3oTW+uxIyJFHJ8Im0k4qBw==", "dev": true, "dependencies": { "@types/cli-progress": "^3.11.0", @@ -2668,20 +2694,6 @@ "node": ">=8" } }, - "node_modules/@oclif/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@oclif/core/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -2698,9 +2710,9 @@ } }, "node_modules/@oclif/core/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@oclif/errors": { @@ -2905,20 +2917,6 @@ "node": ">=8" } }, - "node_modules/@oclif/help/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@oclif/help/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2932,9 +2930,9 @@ } }, "node_modules/@oclif/help/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@oclif/help/node_modules/wrap-ansi": { @@ -3044,9 +3042,9 @@ } }, "node_modules/@oclif/parser/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@oclif/plugin-help": { @@ -3075,18 +3073,19 @@ }, "node_modules/@openzeppelin/contracts5": { "name": "@openzeppelin/contracts", - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.0.tgz", - "integrity": "sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.2.tgz", + "integrity": "sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==", "dev": true }, "node_modules/@openzeppelin/defender-admin-client": { - "version": "1.54.1", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-admin-client/-/defender-admin-client-1.54.1.tgz", - "integrity": "sha512-kRpSUdTsnSqntp4FOXIm95t+6VKHc8CUY2Si71VDuxs0q7HSPZkdpRPSntcolwEzWy9L4a8NS/QMwDF5NJ4X1g==", + "version": "1.54.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-admin-client/-/defender-admin-client-1.54.6.tgz", + "integrity": "sha512-P4lxJDySrekWNuPa7FeyW/UmuxnuIXIAGYr5gZnmnMHRsYNaw+XfgkiCDfoGtjEyJbXYxXttYF6iAZhWQPdf1g==", + "deprecated": "This package has been deprecated and will no longer be maintained, please use @openzeppelin/defender-sdk package instead.", "dev": true, "dependencies": { - "@openzeppelin/defender-base-client": "1.54.1", + "@openzeppelin/defender-base-client": "1.54.6", "axios": "^1.4.0", "ethers": "^5.7.2", "lodash": "^4.17.19", @@ -3142,9 +3141,10 @@ } }, "node_modules/@openzeppelin/defender-base-client": { - "version": "1.54.1", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.54.1.tgz", - "integrity": "sha512-DRGz/7KN3ZQwu28YWMOaojrC7jjPkz/uCwkC8/C8B11qwZhA5qIVvyhYHhhFOCl0J84+E3TNdvkPD2q3p2WaJw==", + "version": "1.54.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.54.6.tgz", + "integrity": "sha512-PTef+rMxkM5VQ7sLwLKSjp2DBakYQd661ZJiSRywx+q/nIpm3B/HYGcz5wPZCA5O/QcEP6TatXXDoeMwimbcnw==", + "deprecated": "This package has been deprecated and will no longer be maintained, please use @openzeppelin/defender-sdk package instead.", "dev": true, "dependencies": { "amazon-cognito-identity-js": "^6.0.1", @@ -3155,9 +3155,9 @@ } }, "node_modules/@openzeppelin/defender-sdk-base-client": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.14.3.tgz", - "integrity": "sha512-4yG9E8N1c/ZP2jNR+Ah19wi7SBKpauAV/VcYcm7rg1dltDbzbH/oZnnXJlymT7IfjTPXkKHW8TPsaqz3EjS7tA==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.15.0.tgz", + "integrity": "sha512-nuf/xegMIuKCO0hMrxI1KQKTzQw1iCl/9kew2nJM9MrFIohhfEXItc5rbJRoV/jehmK/Jhi9ATF9OHH09StEsQ==", "dev": true, "dependencies": { "amazon-cognito-identity-js": "^6.3.6", @@ -3165,12 +3165,12 @@ } }, "node_modules/@openzeppelin/defender-sdk-deploy-client": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.14.3.tgz", - "integrity": "sha512-51WIZJz251lndK7uQU4gBE0gBX+2ZNTgf+hemtJUEPCpHtkooBRFFMID3EPGMKXVqf872pU8K3Huu9PyYQu6bw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.15.0.tgz", + "integrity": "sha512-2ODMN4j5pPYWyIOvA/zRQmJ0tJyqi6NV3S/PyvufBXa3oj/MDnVO5bMGSQFH0M2VE3bg+i/rcUb0hdbX9Rtm5Q==", "dev": true, "dependencies": { - "@openzeppelin/defender-sdk-base-client": "1.14.3", + "@openzeppelin/defender-sdk-base-client": "^1.15.0", "axios": "^1.7.2", "lodash": "^4.17.21" } @@ -3278,16 +3278,18 @@ } }, "node_modules/@openzeppelin/upgrades-core": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.32.0.tgz", - "integrity": "sha512-ZjYB5Ks5Haz8yzJDd9VzTtJyqm746+WYFOi8jeVljyGxC4Xm2wuizf/n1lw0CmCw9seNhD1J1tA4fA6ScXYPDg==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.40.0.tgz", + "integrity": "sha512-4bPSXdEqHsNRL5T1ybPLneWGYjzGl6XWGWkv7aUoFFgz8mOdarstRBX1Wi4XJFw6IeHPUI7mMSQr2jdz8Y2ypQ==", "dev": true, "dependencies": { + "@nomicfoundation/slang": "^0.17.0", "cbor": "^9.0.0", "chalk": "^4.1.0", "compare-versions": "^6.0.0", "debug": "^4.1.1", "ethereumjs-util": "^7.0.3", + "minimatch": "^9.0.5", "minimist": "^1.2.7", "proper-lockfile": "^4.1.1", "solidity-ast": "^0.4.51" @@ -3312,9 +3314,9 @@ } }, "node_modules/@openzeppelin/upgrades-core/node_modules/cbor": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.1.tgz", - "integrity": "sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", "dev": true, "dependencies": { "nofilter": "^3.1.0" @@ -3389,16 +3391,16 @@ } }, "node_modules/@polygon-hermez/vm": { - "version": "5.7.36", - "resolved": "https://registry.npmjs.org/@polygon-hermez/vm/-/vm-5.7.36.tgz", - "integrity": "sha512-BN/42g7NbQZYz1+f2uEaVvZOxf1eCjFKkT/mTCdTK5ARpxDOzBwIVnt3WTjzgUsj7BzDU4btB0ifPNaKKR2Dpw==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/@polygon-hermez/vm/-/vm-6.0.13.tgz", + "integrity": "sha512-PjwXd1Tz18ABf2JefQy20J/M5B5IOGqU3yoHl0TcOGqxxbJ+Z/DRZePkVYgpS2wDh9tudX/o75Dlm3ajG+hClg==", "dev": true, "dependencies": { "@ethereumjs/block": "^3.6.1", "@ethereumjs/blockchain": "^5.5.1", "@ethereumjs/common": "^2.6.2", "@ethereumjs/tx": "^3.5.0", - "@polygon-hermez/zkevm-commonjs": "github:hermeznetwork/zkevm-commonjs#v1.0.0", + "@polygon-hermez/zkevm-commonjs": "github:hermeznetwork/zkevm-commonjs#v6.0.0-fork.9", "async-eventemitter": "^0.2.4", "core-js-pure": "^3.0.1", "debug": "^4.3.3", @@ -3461,15 +3463,15 @@ }, "node_modules/@polygon-hermez/zkevm-commonjs": { "name": "@0xpolygonhermez/zkevm-commonjs", - "version": "1.0.0", - "resolved": "git+ssh://git@github.com/hermeznetwork/zkevm-commonjs.git#34f72fe9f7a4c3c45965742476a87148c9e05c0f", + "version": "5.0.0", + "resolved": "git+ssh://git@github.com/hermeznetwork/zkevm-commonjs.git#1bc8b6729bd8873eba433376cb6f2565b8c9ad41", "dev": true, "license": "pending", "dependencies": { "@ethereumjs/block": "^3.6.2", "@ethereumjs/tx": "^3.4.0", "@polygon-hermez/common": "2.6.4", - "@polygon-hermez/vm": "5.7.30", + "@polygon-hermez/vm": "6.0.12", "ethereumjs-util": "^7.1.4", "ethers": "^5.5.4", "ffjavascript": "^0.2.55", @@ -3478,16 +3480,16 @@ } }, "node_modules/@polygon-hermez/zkevm-commonjs/node_modules/@polygon-hermez/vm": { - "version": "5.7.30", - "resolved": "https://registry.npmjs.org/@polygon-hermez/vm/-/vm-5.7.30.tgz", - "integrity": "sha512-HxmrGuRpYsgwd4rnvYNQ4OR77OKdAbUsAD1Z6PoEvV18NHsMv6JGpMnvnSAseiCBCyqTHjnFqWynoQ1nl0Qr6g==", + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@polygon-hermez/vm/-/vm-6.0.12.tgz", + "integrity": "sha512-X882QZUmbLFRBgD+uA5I4bP+i62bmixRgXsDu9vEhy7fVOfZvH4AbzgZ9lOivylkdj7oNfJO1WC5fvugiAa6pw==", "dev": true, "dependencies": { "@ethereumjs/block": "^3.6.1", "@ethereumjs/blockchain": "^5.5.1", "@ethereumjs/common": "^2.6.2", "@ethereumjs/tx": "^3.5.0", - "@polygon-hermez/zkevm-commonjs": "github:hermeznetwork/zkevm-commonjs#v0.5.0.1", + "@polygon-hermez/zkevm-commonjs": "github:hermeznetwork/zkevm-commonjs#v1.0.0", "async-eventemitter": "^0.2.4", "core-js-pure": "^3.0.1", "debug": "^4.3.3", @@ -3629,45 +3631,52 @@ "ms": "^2.1.1" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "peer": true + }, "node_modules/@scure/base": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", - "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", "dev": true, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", - "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", "dev": true, "dependencies": { - "@noble/curves": "~1.1.0", - "@noble/hashes": "~1.3.1", - "@scure/base": "~1.1.0" + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, "dependencies": { - "@noble/hashes": "1.3.1" + "@noble/hashes": "1.4.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, "engines": { "node": ">= 16" @@ -3677,13 +3686,25 @@ } }, "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", "dev": true, "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "engines": { + "node": ">= 16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -3792,21 +3813,21 @@ } }, "node_modules/@smithy/types": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.7.0.tgz", - "integrity": "sha512-1OIFyhK+vOkMbu4aN2HZz/MomREkrAC/HqY5mlJMUJfGrPRwijJDTeiN8Rnj9zUaB8ogXAfIOtZrrgqZ4w7Wnw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.5.0.tgz", + "integrity": "sha512-QN0twHNfe8mNJdH9unwsCK13GURU7oEAZqkBI+rsvpv1jrmserO+WnLE7jidR9W/1dxwZ0u/CB01mV2Gms/K2Q==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/types/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@solidity-parser/parser": { @@ -3820,9 +3841,9 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true }, "node_modules/@tsconfig/node12": { @@ -3876,31 +3897,31 @@ } }, "node_modules/@types/abstract-leveldown": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-7.2.3.tgz", - "integrity": "sha512-YAdL8tIYbiKoFjAf/0Ir3mvRJ/iFvBP/FK0I8Xa5rGWgVcq0xWOEInzlJfs6TIPWFweEOTKgNSBdxneUcHRvaw==", + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-7.2.5.tgz", + "integrity": "sha512-/2B0nQF4UdupuxeKTJA2+Rj1D+uDemo6P4kMwKCpbfpnzeVaWSELTsAw4Lxn3VJD6APtRrZOCuYo+4nHUQfTfg==", "dev": true }, "node_modules/@types/bn.js": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.2.tgz", - "integrity": "sha512-dkpZu0szUtn9UXTmw+e0AJFd4D2XAxDnsCLdc05SfqpqzPEBft8eQr8uaFitfo/dUUOZERaLec2hHMG87A4Dxg==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", + "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/chai": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.8.tgz", - "integrity": "sha512-yW/qTM4mRBBcsA9Xw9FbcImYtFPY7sgr+G/O5RDYVmxiy9a+pE5FyoFUi8JYCZY5nicj8atrr1pcfPiYpeNGOA==", + "version": "4.3.20", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", + "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", "dev": true, "peer": true }, "node_modules/@types/chai-as-promised": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.6.tgz", - "integrity": "sha512-cQLhk8fFarRVZAXUQV1xEnZgMoPxqKojBvRkqPCKPQCzEhpbbSKl1Uu75kDng7k5Ln6LQLUmNBjLlFthCgm1NA==", + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", "dev": true, "peer": true, "dependencies": { @@ -3908,9 +3929,9 @@ } }, "node_modules/@types/cli-progress": { - "version": "3.11.3", - "resolved": "https://registry.npmjs.org/@types/cli-progress/-/cli-progress-3.11.3.tgz", - "integrity": "sha512-/+C9xAdVtc+g5yHHkGBThgAA8rYpi5B+2ve3wLtybYj0JHEBs57ivR4x/zGfSsplRnV+psE91Nfin1soNKqz5Q==", + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/@types/cli-progress/-/cli-progress-3.11.6.tgz", + "integrity": "sha512-cE3+jb9WRlu+uOSAugewNpITJDt1VF8dHOopPO4IABFc3SXYL5WE/+PTz/FCdZRRfIujiWW3n3aMbv1eIGVRWA==", "dev": true, "dependencies": { "@types/node": "*" @@ -3955,9 +3976,9 @@ "peer": true }, "node_modules/@types/level-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/level-errors/-/level-errors-3.0.0.tgz", - "integrity": "sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/level-errors/-/level-errors-3.0.2.tgz", + "integrity": "sha512-gyZHbcQ2X5hNXf/9KS2qGEmgDe9EN2WDM3rJ5Ele467C0nA1sLhtmv1bZiPMDYfAYCfPWft0uQIaTvXbASSTRA==", "dev": true }, "node_modules/@types/levelup": { @@ -3994,25 +4015,25 @@ } }, "node_modules/@types/mocha": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.2.tgz", - "integrity": "sha512-NaHL0+0lLNhX6d9rs+NSt97WH/gIlRHmszXbQ/8/MV/eVcFNdeJ/GYhrFuUc8K7WuPhRhTSdMkCp8VMzhUq85w==", + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", + "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", "dev": true, "peer": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~6.19.2" } }, "node_modules/@types/node-fetch": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.6.tgz", - "integrity": "sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", "dev": true, "dependencies": { "@types/node": "*", @@ -4020,9 +4041,9 @@ } }, "node_modules/@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", "dev": true, "dependencies": { "@types/node": "*" @@ -4035,9 +4056,9 @@ "dev": true }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", "dev": true, "peer": true }, @@ -4051,27 +4072,33 @@ } }, "node_modules/@types/secp256k1": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.4.tgz", - "integrity": "sha512-oN0PFsYxDZnX/qSJ5S5OwaEDTYfekhvaM5vqui2bu1AA39pKofmgL104Q29KiOXizXS2yLjSzc5YdTyMKdcy4A==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", + "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/yargs": { - "version": "17.0.28", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz", - "integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, "node_modules/@yarnpkg/lockfile": { @@ -4127,22 +4154,10 @@ "ieee754": "^1.1.13" } }, - "node_modules/abstract-leveldown/node_modules/level-supports": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", - "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", - "dev": true, - "dependencies": { - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -4161,24 +4176,17 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/adm-zip": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", @@ -4237,9 +4245,9 @@ } }, "node_modules/amazon-cognito-identity-js": { - "version": "6.3.7", - "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.7.tgz", - "integrity": "sha512-tSjnM7KyAeOZ7UMah+oOZ6cW4Gf64FFcc7BE2l7MTcp7ekAPrXaCbpcW2xEpH1EiDS4cPcAouHzmCuc2tr72vQ==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.12.tgz", + "integrity": "sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg==", "dev": true, "dependencies": { "@aws-crypto/sha256-js": "1.2.2", @@ -4269,20 +4277,6 @@ "string-width": "^4.1.0" } }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -4350,7 +4344,8 @@ "version": "0.5.0-alpha.4", "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/anymatch": { "version": "3.1.3", @@ -4388,29 +4383,34 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -4439,37 +4439,19 @@ "node": ">=0.10.0" } }, - "node_modules/array.prototype.findlast": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.3.tgz", - "integrity": "sha512-kcBubumjciBg4JKp5KTKtI7ec7tRefPk88yjkWJwaVKYd9QfTaxcsOxoMNKd7iBr447zCfDV0z1kOF47umv42g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4517,17 +4499,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, + "peer": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -4624,10 +4608,14 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "peer": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -4645,15 +4633,15 @@ } }, "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", "dev": true }, "node_modules/axios": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", - "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, "dependencies": { "follow-redirects": "^1.15.6", @@ -4662,9 +4650,9 @@ } }, "node_modules/b4a": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", - "integrity": "sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", "dev": true }, "node_modules/balanced-match": { @@ -4674,9 +4662,9 @@ "dev": true }, "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.10.tgz", + "integrity": "sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==", "dev": true, "dependencies": { "safe-buffer": "^5.0.1" @@ -4724,12 +4712,15 @@ "dev": true }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/blake-hash": { @@ -4865,20 +4856,6 @@ "node": ">=8" } }, - "node_modules/boxen/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/boxen/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4892,22 +4869,21 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -4982,15 +4958,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/buffer-xor": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", @@ -5010,13 +4977,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5076,9 +5049,9 @@ } }, "node_modules/chai": { - "version": "4.3.10", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", - "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, "peer": true, "dependencies": { @@ -5088,23 +5061,23 @@ "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.8" + "type-detect": "^4.1.0" }, "engines": { "node": ">=4" } }, "node_modules/chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", + "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", "dev": true, "peer": true, "dependencies": { "check-error": "^1.0.2" }, "peerDependencies": { - "chai": ">= 2.1.2 < 5" + "chai": ">= 2.1.2 < 6" } }, "node_modules/chalk": { @@ -5145,42 +5118,18 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" + "node": ">= 14.16.0" }, - "engines": { - "node": ">= 6" + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/ci-info": { @@ -5292,20 +5241,6 @@ "node": ">=4" } }, - "node_modules/cli-progress/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cli-table3": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", @@ -5323,6 +5258,53 @@ "colors": "^1.1.2" } }, + "node_modules/cli-table3/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "peer": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-table3/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -5334,20 +5316,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -5459,9 +5427,9 @@ "dev": true }, "node_modules/compare-versions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", - "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", "dev": true }, "node_modules/concat-map": { @@ -5535,9 +5503,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.33.0.tgz", - "integrity": "sha512-FKSIDtJnds/YFIEaZ4HszRX7hkxGpNKM7FC9aJ9WLJbSd3lD4vOltFuVIBLR8asSx9frkTSqL0dw90SKQxgKrg==", + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.38.1.tgz", + "integrity": "sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==", "dev": true, "hasInstallScript": true, "funding": { @@ -5632,6 +5600,60 @@ "node": ">=0.10" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "peer": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/death": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", @@ -5640,12 +5662,12 @@ "peer": true }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -5669,9 +5691,9 @@ } }, "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, "peer": true, "dependencies": { @@ -5750,30 +5772,21 @@ "ieee754": "^1.1.13" } }, - "node_modules/deferred-leveldown/node_modules/level-supports": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", - "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", - "dev": true, - "dependencies": { - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { @@ -5811,25 +5824,10 @@ "node": ">= 0.8" } }, - "node_modules/detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", - "dev": true, - "peer": true, - "dependencies": { - "address": "^1.0.1", - "debug": "4" - }, - "bin": { - "detect": "bin/detect-port.js", - "detect-port": "bin/detect-port.js" - } - }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" @@ -5892,9 +5890,9 @@ } }, "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "dependencies": { "jake": "^10.8.5" @@ -5992,50 +5990,58 @@ } }, "node_modules/es-abstract": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", - "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, + "peer": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -6044,27 +6050,62 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, + "peer": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, + "peer": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -6072,6 +6113,7 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, + "peer": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -6085,9 +6127,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -6191,18 +6233,20 @@ } }, "node_modules/eslint": { - "version": "8.51.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", - "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.51.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -6286,9 +6330,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, "peer": true, "dependencies": { @@ -6314,35 +6358,48 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, "peer": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -6368,6 +6425,19 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-mocha": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-9.0.0.tgz", @@ -6454,6 +6524,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6509,6 +6589,18 @@ "node": ">=8" } }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6553,9 +6645,9 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -6751,12 +6843,24 @@ } }, "node_modules/ethereum-bloom-filters": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", - "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz", + "integrity": "sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==", "dev": true, "dependencies": { - "js-sha3": "^0.8.0" + "@noble/hashes": "^1.4.0" + } + }, + "node_modules/ethereum-bloom-filters/node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "dev": true, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/ethereum-cryptography": { @@ -6906,9 +7010,9 @@ } }, "node_modules/ethers": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.8.0.tgz", - "integrity": "sha512-zrFbmQRlraM+cU5mE4CZTLBurZTs2gdp2ld0nG/f3ecBK+x6lZ69KSxBqZ4NjclxwfTxl5LeNufcBbMsTdY53Q==", + "version": "6.13.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.3.tgz", + "integrity": "sha512-/DzbZOLVtoO4fKvvQwpEucHAQgIwBGWuRvBdwE/lMXgXvvHHTSkn7XqAQ2b+gjJzZDJjWA9OD05bVceVOsBHbg==", "dev": true, "funding": [ { @@ -6922,13 +7026,13 @@ ], "peer": true, "dependencies": { - "@adraffy/ens-normalize": "1.10.0", + "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", "@types/node": "18.15.13", "aes-js": "4.0.0-beta.5", "tslib": "2.4.0", - "ws": "8.5.0" + "ws": "8.17.1" }, "engines": { "node": ">=14.0.0" @@ -7020,9 +7124,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -7059,24 +7163,31 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", + "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "dev": true, + "peer": true + }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" } }, "node_modules/ffjavascript": { - "version": "0.2.60", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.60.tgz", - "integrity": "sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==", + "version": "0.2.63", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.63.tgz", + "integrity": "sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==", "dev": true, "dependencies": { "wasmbuilder": "0.0.16", "wasmcurves": "0.2.2", - "web-worker": "^1.2.0" + "web-worker": "1.2.0" } }, "node_modules/file-entry-cache": { @@ -7100,15 +7211,6 @@ "minimatch": "^5.0.1" } }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -7122,9 +7224,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -7181,9 +7283,9 @@ } }, "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { "flatted": "^3.2.9", @@ -7191,19 +7293,19 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -7225,6 +7327,7 @@ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, + "peer": true, "dependencies": { "is-callable": "^1.1.3" } @@ -7239,9 +7342,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "dependencies": { "asynckit": "^0.4.0", @@ -7314,6 +7417,7 @@ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, + "peer": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -7338,6 +7442,7 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16540,15 +16645,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -16574,13 +16683,15 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -16616,6 +16727,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -16644,6 +16756,28 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -16686,9 +16820,9 @@ } }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -16701,12 +16835,14 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "peer": true, "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -16823,14 +16959,14 @@ } }, "node_modules/hardhat": { - "version": "2.22.4", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.4.tgz", - "integrity": "sha512-09qcXJFBHQUaraJkYNr7XlmwjOj27xBB0SL2rYS024hTj9tPMbp26AFjlf5quBMO9SR4AJFg+4qWahcYcvXBuQ==", + "version": "2.22.13", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.13.tgz", + "integrity": "sha512-psVJX4FSXDpSXwsU8OcKTJN04pQEj9cFBMX5OPko+OFwbIoiOpvRmafa954/UaA1934npTj8sV3gaTSdx9bPbA==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.3.7", + "@nomicfoundation/edr": "^0.6.3", "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-tx": "5.0.4", "@nomicfoundation/ethereumjs-util": "9.0.4", @@ -16843,7 +16979,7 @@ "ansi-escapes": "^4.3.0", "boxen": "^5.1.2", "chalk": "^2.4.2", - "chokidar": "^3.4.0", + "chokidar": "^4.0.0", "ci-info": "^2.0.0", "debug": "^4.1.1", "enquirer": "^2.3.0", @@ -16856,6 +16992,7 @@ "glob": "7.2.0", "immutable": "^4.0.0-rc.12", "io-ts": "1.10.4", + "json-stream-stringify": "^3.1.4", "keccak": "^3.0.2", "lodash": "^4.17.11", "mnemonist": "^0.38.0", @@ -16864,7 +17001,7 @@ "raw-body": "^2.4.1", "resolve": "1.17.0", "semver": "^6.3.0", - "solc": "0.7.3", + "solc": "0.8.26", "source-map-support": "^0.5.13", "stacktrace-parser": "^0.1.10", "tsort": "0.0.1", @@ -16889,9 +17026,9 @@ } }, "node_modules/hardhat-dependency-compiler": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hardhat-dependency-compiler/-/hardhat-dependency-compiler-1.1.3.tgz", - "integrity": "sha512-bCDqsOxGST6WkbMvj4lPchYWidNSSBm5CFnkyAex1T11cGmr9otZTGl81W6f9pmrtBXbKCvr3OSuNJ6Q394sAw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/hardhat-dependency-compiler/-/hardhat-dependency-compiler-1.2.1.tgz", + "integrity": "sha512-xG5iwbspTtxOEiP5UsPngEYQ1Hg+fjTjliapIjdTQmwGkCPofrsDhQDV2O/dopcYzcR68nTx2X8xTewYHgA2rQ==", "dev": true, "engines": { "node": ">=14.14.0" @@ -16901,9 +17038,9 @@ } }, "node_modules/hardhat-gas-reporter": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz", - "integrity": "sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", + "integrity": "sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==", "dev": true, "peer": true, "dependencies": { @@ -16960,6 +17097,15 @@ "@scure/base": "~1.1.0" } }, + "node_modules/hardhat/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/hardhat/node_modules/ethereum-cryptography": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", @@ -17065,61 +17211,25 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hardhat/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/hardhat/node_modules/solc": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", - "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", + "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", "dev": true, "dependencies": { "command-exists": "^1.2.8", - "commander": "3.0.2", + "commander": "^8.1.0", "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", "js-sha3": "0.8.0", "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", "semver": "^5.5.0", "tmp": "0.0.33" }, "bin": { - "solcjs": "solcjs" + "solcjs": "solc.js" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": ">=10.0.0" } }, "node_modules/hardhat/node_modules/solc/node_modules/semver": { @@ -17141,9 +17251,9 @@ } }, "node_modules/hardhat/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, "engines": { "node": ">=8.3.0" @@ -17161,20 +17271,12 @@ } } }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, + "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17189,21 +17291,21 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -17225,12 +17327,13 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "peer": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -17263,6 +17366,18 @@ "minimalistic-assert": "^1.0.1" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -17276,8 +17391,7 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/hmac-drbg": { "version": "1.0.1", @@ -17427,9 +17541,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" @@ -17442,9 +17556,9 @@ "dev": true }, "node_modules/immutable": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", "dev": true }, "node_modules/import-fresh": { @@ -17485,6 +17599,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "dependencies": { "once": "^1.3.0", @@ -17505,13 +17620,14 @@ "peer": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, + "peer": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -17547,14 +17663,17 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, + "peer": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -17571,6 +17690,7 @@ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, + "peer": true, "dependencies": { "has-bigints": "^1.0.1" }, @@ -17595,6 +17715,7 @@ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, + "peer": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -17611,6 +17732,7 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "peer": true, "engines": { "node": ">= 0.4" }, @@ -17631,12 +17753,31 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "peer": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -17647,6 +17788,7 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "peer": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -17713,10 +17855,11 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, + "peer": true, "engines": { "node": ">= 0.4" }, @@ -17738,6 +17881,7 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, + "peer": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -17771,6 +17915,7 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, + "peer": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -17783,12 +17928,16 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -17799,6 +17948,7 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "peer": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -17814,6 +17964,7 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, + "peer": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -17825,12 +17976,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "peer": true, "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -17874,6 +18026,7 @@ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, + "peer": true, "dependencies": { "call-bind": "^1.0.2" }, @@ -17922,9 +18075,9 @@ "dev": true }, "node_modules/jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", "dev": true, "dependencies": { "async": "^3.2.3", @@ -17955,11 +18108,21 @@ } }, "node_modules/jake/node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/jake/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -18003,6 +18166,18 @@ "node": ">=8" } }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/jake/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -18069,6 +18244,15 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-stream-stringify": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", + "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", + "dev": true, + "engines": { + "node": ">=7.10.1" + } + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -18291,6 +18475,18 @@ "node": ">=6" } }, + "node_modules/level-supports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", + "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", + "dev": true, + "dependencies": { + "xtend": "^4.0.2" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/level-ws": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-2.0.0.tgz", @@ -18321,18 +18517,6 @@ "node": ">=6" } }, - "node_modules/levelup/node_modules/level-supports": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", - "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", - "dev": true, - "dependencies": { - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -18651,24 +18835,12 @@ "ieee754": "^1.1.13" } }, - "node_modules/memdown/node_modules/immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg==", - "dev": true - }, - "node_modules/memdown/node_modules/level-supports": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-1.0.1.tgz", - "integrity": "sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg==", - "dev": true, - "dependencies": { - "xtend": "^4.0.2" - }, - "engines": { - "node": ">=6" - } - }, + "node_modules/memdown/node_modules/immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg==", + "dev": true + }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -18708,12 +18880,12 @@ "dev": true }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -18773,15 +18945,18 @@ "dev": true }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -18815,32 +18990,31 @@ } }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", + "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -18848,28 +19022,30 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/mocha/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, "node_modules/mocha/node_modules/escape-string-regexp": { @@ -18884,6 +19060,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/mocha/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -18894,9 +19102,9 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -18905,11 +19113,17 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "node_modules/mocha/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", @@ -18927,9 +19141,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/nanoassert": { @@ -18938,18 +19152,6 @@ "integrity": "sha512-7vO7n28+aYO4J+8w96AzhmU8G+Y/xpPDJz/se19ICsqj/momRbb9mh9ZUtkoJ5X3nTnPdhEJyc0qnM6yAsHBaA==", "dev": true }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -19014,9 +19216,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", - "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", "dev": true, "bin": { "node-gyp-build": "bin.js", @@ -19125,10 +19327,13 @@ } }, "node_modules/object-inspect": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", - "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -19152,13 +19357,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -19170,29 +19375,30 @@ } }, "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -19202,28 +19408,30 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -19264,17 +19472,17 @@ } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -19362,12 +19570,6 @@ "node": ">=4" } }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", - "dev": true - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -19525,6 +19727,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -19668,16 +19871,14 @@ "dev": true }, "node_modules/pg": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", - "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.0.tgz", + "integrity": "sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==", "dev": true, "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", + "pg-connection-string": "^2.7.0", + "pg-pool": "^3.7.0", + "pg-protocol": "^1.7.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, @@ -19704,9 +19905,9 @@ "optional": true }, "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.7.0.tgz", + "integrity": "sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==", "dev": true }, "node_modules/pg-int8": { @@ -19719,18 +19920,18 @@ } }, "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz", + "integrity": "sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g==", "dev": true, "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz", + "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==", "dev": true }, "node_modules/pg-types": { @@ -19801,6 +20002,16 @@ "node": ">=0.10.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -19872,51 +20083,32 @@ } }, "node_modules/prettier-plugin-solidity": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.3.tgz", - "integrity": "sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.4.1.tgz", + "integrity": "sha512-Mq8EtfacVZ/0+uDKTtHZGW3Aa7vEbX/BNx63hmVg6YTiTXSiuKP0amj0G6pGwjmLaOfymWh3QgXEZkjQbU8QRg==", "dev": true, "dependencies": { - "@solidity-parser/parser": "^0.16.0", - "semver": "^7.3.8", - "solidity-comments-extractor": "^0.0.7" + "@solidity-parser/parser": "^0.18.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=12" + "node": ">=16" }, "peerDependencies": { - "prettier": ">=2.3.0 || >=3.0.0-alpha.0" + "prettier": ">=2.3.0" } }, "node_modules/prettier-plugin-solidity/node_modules/@solidity-parser/parser": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.1.tgz", - "integrity": "sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==", - "dev": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } - }, - "node_modules/prettier-plugin-solidity/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", + "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", + "dev": true }, "node_modules/prettier-plugin-solidity/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -19924,12 +20116,6 @@ "node": ">=10" } }, - "node_modules/prettier-plugin-solidity/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -20143,15 +20329,16 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/rechoir": { @@ -20180,6 +20367,30 @@ "node": ">=6.0.0" } }, + "node_modules/recursive-readdir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/recursive-readdir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/redeyed": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", @@ -20213,14 +20424,16 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -20394,6 +20607,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -20457,13 +20671,14 @@ "dev": true }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -20478,7 +20693,8 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/safe-buffer": { "version": "5.2.1", @@ -20501,15 +20717,19 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -20563,10 +20783,22 @@ "dev": true, "peer": true }, + "node_modules/sc-istanbul/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/sc-istanbul/node_modules/glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "peer": true, "dependencies": { @@ -20618,6 +20850,19 @@ "node": ">=4" } }, + "node_modules/sc-istanbul/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/sc-istanbul/node_modules/resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -20697,9 +20942,9 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "dependencies": { "randombytes": "^2.1.0" @@ -20711,15 +20956,34 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "peer": true, "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -20804,14 +21068,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -20970,6 +21238,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { "glob": "^7.1.3" @@ -20988,40 +21257,30 @@ } }, "node_modules/solidity-ast": { - "version": "0.4.55", - "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.55.tgz", - "integrity": "sha512-qeEU/r/K+V5lrAw8iswf2/yfWAnSGs3WKPHI+zAFKFjX0dIBVXEU/swQ8eJQYHf6PJWUZFO2uWV4V1wEOkeQbA==", - "dev": true, - "dependencies": { - "array.prototype.findlast": "^1.2.2" - } - }, - "node_modules/solidity-comments-extractor": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", - "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==", + "version": "0.4.59", + "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.59.tgz", + "integrity": "sha512-I+CX0wrYUN9jDfYtcgWSe+OAowaXy8/1YQy7NS4ni5IBDmIYBq7ZzaP/7QqouLjzZapmQtvGLqCaYgoUWqBo5g==", "dev": true }, "node_modules/solidity-coverage": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.5.tgz", - "integrity": "sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==", + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.13.tgz", + "integrity": "sha512-RiBoI+kF94V3Rv0+iwOj3HQVSqNzA9qm/qDP1ZDXK5IX0Cvho1qiz8hAXTsAo6KOIUeP73jfscq0KlLqVxzGWA==", "dev": true, "peer": true, "dependencies": { "@ethersproject/abi": "^5.0.9", - "@solidity-parser/parser": "^0.16.0", + "@solidity-parser/parser": "^0.18.0", "chalk": "^2.4.2", "death": "^1.1.0", - "detect-port": "^1.3.0", "difflib": "^0.2.4", "fs-extra": "^8.1.0", "ghost-testrpc": "^0.0.2", "global-modules": "^2.0.0", "globby": "^10.0.1", "jsonschema": "^1.2.4", - "lodash": "^4.17.15", - "mocha": "10.2.0", + "lodash": "^4.17.21", + "mocha": "^10.2.0", "node-emoji": "^1.10.0", "pify": "^4.0.1", "recursive-readdir": "^2.2.2", @@ -21038,14 +21297,11 @@ } }, "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.1.tgz", - "integrity": "sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", + "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", "dev": true, - "peer": true, - "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" - } + "peer": true }, "node_modules/solidity-coverage/node_modules/fs-extra": { "version": "8.1.0", @@ -21072,28 +21328,12 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/solidity-coverage/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/solidity-coverage/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -21111,13 +21351,6 @@ "node": ">= 4.0.0" } }, - "node_modules/solidity-coverage/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true - }, "node_modules/solidity-docgen": { "version": "0.5.17", "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.5.17.tgz", @@ -21141,15 +21374,6 @@ "solidity-docgen": "dist/cli.js" } }, - "node_modules/solidity-docgen/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/solidity-docgen/node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -21170,18 +21394,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/solidity-docgen/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/solidity-docgen/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -21195,13 +21407,10 @@ } }, "node_modules/solidity-docgen/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -21218,12 +21427,6 @@ "node": ">=8" } }, - "node_modules/solidity-docgen/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", @@ -21268,9 +21471,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -21284,9 +21487,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", "dev": true }, "node_modules/split2": { @@ -21305,9 +21508,9 @@ "dev": true }, "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, "dependencies": { "asn1": "~0.2.3", @@ -21382,61 +21585,30 @@ "peer": true }, "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "peer": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "peer": true, "dependencies": { - "ansi-regex": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -21446,28 +21618,33 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -21604,9 +21781,9 @@ } }, "node_modules/table": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", - "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", + "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "dev": true, "peer": true, "dependencies": { @@ -21657,16 +21834,16 @@ } }, "node_modules/table/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "peer": true, "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -21680,21 +21857,6 @@ "dev": true, "peer": true }, - "node_modules/table/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "peer": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/test-value": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", @@ -21770,15 +21932,16 @@ "peer": true }, "node_modules/then-request/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz", + "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==", "dev": true, "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "mime-types": "^2.1.12", + "safe-buffer": "^5.2.1" }, "engines": { "node": ">= 0.12" @@ -21831,9 +21994,9 @@ } }, "node_modules/tough-cookie/node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -21974,9 +22137,9 @@ "dev": true }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -22026,9 +22189,9 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "peer": true, "dependencies": { @@ -22100,9 +22263,9 @@ } }, "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, "peer": true, "engines": { @@ -22146,6 +22309,17 @@ "typescript": ">=4.3.0" } }, + "node_modules/typechain/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/typechain/node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -22165,6 +22339,7 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "peer": true, "dependencies": { @@ -22192,6 +22367,19 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/typechain/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/typechain/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -22216,29 +22404,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -22248,16 +22439,18 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, + "peer": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -22267,14 +22460,21 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, + "peer": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -22288,9 +22488,9 @@ "peer": true }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "peer": true, "bin": { @@ -22312,9 +22512,9 @@ } }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, "optional": true, "bin": { @@ -22329,6 +22529,7 @@ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, + "peer": true, "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -22340,9 +22541,9 @@ } }, "node_modules/undici": { - "version": "5.26.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.3.tgz", - "integrity": "sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw==", + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", "dev": true, "dependencies": { "@fastify/busboy": "^2.0.0" @@ -22352,9 +22553,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, "node_modules/unfetch": { @@ -22364,9 +22565,9 @@ "dev": true }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -22391,13 +22592,16 @@ } }, "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", "dev": true, "dependencies": { "punycode": "^1.4.1", - "qs": "^6.11.2" + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/url/node_modules/punycode": { @@ -22407,12 +22611,12 @@ "dev": true }, "node_modules/url/node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -22494,9 +22698,9 @@ "dev": true }, "node_modules/web3-utils": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.2.tgz", - "integrity": "sha512-TdApdzdse5YR+5GCX/b/vQnhhbj1KSAtfrDtRW7YS0kcWp1gkJsN62gw6GzCaNTeXookB7UrLtmDUuMv65qgow==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", + "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", "dev": true, "dependencies": { "@ethereumjs/util": "^8.1.0", @@ -22513,21 +22717,21 @@ } }, "node_modules/web3-utils/node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, "dependencies": { - "@noble/hashes": "1.3.1" + "@noble/hashes": "1.4.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/web3-utils/node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, "engines": { "node": ">= 16" @@ -22537,15 +22741,15 @@ } }, "node_modules/web3-utils/node_modules/ethereum-cryptography": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz", - "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "dev": true, "dependencies": { - "@noble/curves": "1.1.0", - "@noble/hashes": "1.3.1", - "@scure/bip32": "1.3.1", - "@scure/bip39": "1.2.1" + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" } }, "node_modules/webidl-conversions": { @@ -22584,6 +22788,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, + "peer": true, "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -22602,16 +22807,17 @@ "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, + "peer": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -22632,20 +22838,6 @@ "node": ">=8" } }, - "node_modules/widest-line/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", @@ -22663,7 +22855,6 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -22699,9 +22890,9 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "node_modules/wrap-ansi": { @@ -22754,20 +22945,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -22775,9 +22952,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "peer": true, "engines": { @@ -22785,7 +22962,7 @@ }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -22848,9 +23025,9 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "engines": { "node": ">=10" @@ -22871,20 +23048,6 @@ "node": ">=10" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 1ce8833ba..5976a2e91 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "homepage": "https://github.com/0xPolygonHermez/contracts-zkEVM#readme", "license": "pending", "devDependencies": { - "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#main", + "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v8.0.0-fork.12", "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@openzeppelin/contracts": "4.8.2", "@openzeppelin/contracts-upgradeable": "4.8.2", From 0440e6c0ed3378976bf1baa809452cd687a6ea60 Mon Sep 17 00:00:00 2001 From: Ignasi Date: Mon, 21 Oct 2024 10:58:43 +0200 Subject: [PATCH 3/8] Internal audit fixes + new coverage Update bridge at create rollup for vanilla clients Review update --- .github/workflows/build-docker.yml | 2 +- .github/workflows/build-push-docker.yml | 2 +- .github/workflows/compile.yml | 2 +- .github/workflows/main.yml | 2 +- .gitignore | 2 + .../IBasePolygonZkEVMGlobalExitRoot.sol | 4 +- contracts/v2/PolygonZkEVMBridgeV2.sol | 4 +- .../interfaces/IBridgeL2SovereignChains.sol | 21 ++ .../BridgeL2SovereignChain.sol | 63 ++++- .../GlobalExitRootManagerL2SovereignChain.sol | 40 ++-- deployment/v2/1_createGenesis.ts | 5 +- deployment/v2/4_createRollup.ts | 171 +++++++++----- .../v2/create_rollup_parameters.json.example | 9 +- deployment/v2/deploy_parameters.json.example | 3 +- deployment/v2/utils/updateVanillaGenesis.ts | 219 ++++++++++++++++++ docker/scripts/v2/deploy-dockerv2.sh | 2 + hardhat.config.ts | 2 +- package-lock.json | 23 +- ...dgeL2GasTokenMappedSovereignChains.test.ts | 26 --- .../BridgeL2GasTokensSovereignChains.test.ts | 112 ++++----- .../BridgeL2SovereignChain.test.ts | 103 +++----- 21 files changed, 533 insertions(+), 284 deletions(-) create mode 100644 deployment/v2/utils/updateVanillaGenesis.ts diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index c3f4432f5..f03959069 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] steps: - name: Use Node.js ${{ matrix.node-version }} diff --git a/.github/workflows/build-push-docker.yml b/.github/workflows/build-push-docker.yml index e434c236b..de5067b47 100644 --- a/.github/workflows/build-push-docker.yml +++ b/.github/workflows/build-push-docker.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - node-version: [16.x] + node-version: [20.x] steps: - name: Use Node.js ${{ matrix.node-version }} diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 4f5729da2..07b035cdf 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: - node-version: [16.x] + node-version: [20.x] steps: - name: Use Node.js ${{ matrix.node-version }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d72f97ca9..4d11b2e18 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: - node-version: [16.x] + node-version: [20.x] steps: - name: Use Node.js ${{ matrix.node-version }} diff --git a/.gitignore b/.gitignore index ca2367c8b..0fdae8914 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ typechain-types/ create_rollup_parameters.json docker/deploymentOutput + +.DS_Store diff --git a/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol b/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol index 383b58ff0..d8e149fd8 100644 --- a/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol +++ b/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol @@ -9,9 +9,9 @@ interface IBasePolygonZkEVMGlobalExitRoot { error OnlyAllowedContracts(); /** - * @dev Thrown when the caller is not the coinbase + * @dev Thrown when the caller is not the coinbase neither the globalExitRootUpdater */ - error OnlyAggOracleOrCoinbase(); + error OnlyGlobalExitRootUpdater(); /** * @dev Thrown when trying to insert a global exit root that is already set diff --git a/contracts/v2/PolygonZkEVMBridgeV2.sol b/contracts/v2/PolygonZkEVMBridgeV2.sol index 4b8eea592..4a705c313 100644 --- a/contracts/v2/PolygonZkEVMBridgeV2.sol +++ b/contracts/v2/PolygonZkEVMBridgeV2.sol @@ -740,7 +740,7 @@ contract PolygonZkEVMBridgeV2 is * @notice Function to activate the emergency state " Only can be called by the Polygon ZK-EVM in extreme situations */ - function activateEmergencyState() external onlyRollupManager { + function activateEmergencyState() external virtual onlyRollupManager { _activateEmergencyState(); } @@ -748,7 +748,7 @@ contract PolygonZkEVMBridgeV2 is * @notice Function to deactivate the emergency state " Only can be called by the Polygon ZK-EVM */ - function deactivateEmergencyState() external onlyRollupManager { + function deactivateEmergencyState() external virtual onlyRollupManager { _deactivateEmergencyState(); } diff --git a/contracts/v2/interfaces/IBridgeL2SovereignChains.sol b/contracts/v2/interfaces/IBridgeL2SovereignChains.sol index 195746aa5..6948e5fbb 100644 --- a/contracts/v2/interfaces/IBridgeL2SovereignChains.sol +++ b/contracts/v2/interfaces/IBridgeL2SovereignChains.sol @@ -46,6 +46,27 @@ interface IBridgeL2SovereignChains is IPolygonZkEVMBridgeV2 { */ error InvalidInitializeFunction(); + /** + * @dev Thrown when initializing calling a function with invalid arrays length + */ + error InputArraysLengthMismatch(); + + /** + * @dev Thrown when trying to map a token that is already mapped + */ + error TokenAlreadyMapped(); + + /** + * @dev Thrown when trying to remove a legacy mapped token that has nor previously been remapped + */ + error TokenNotRemapped(); + + /** + * @dev Thrown when trying to set a custom wrapper for weth on a gas token network + */ + error WETHRemappingNotSupportedOnGasTokenNetworks(); + + function initialize( uint32 _networkID, address _gasTokenAddress, diff --git a/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol b/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol index 686c49366..214c9b9c5 100644 --- a/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol +++ b/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol @@ -52,7 +52,7 @@ contract BridgeL2SovereignChain is /** * @dev Emitted when a remapped token is removed from mapping */ - event RemoveSovereignTokenAddress(address sovereignTokenAddress); + event RemoveLegacySovereignTokenAddress(address sovereignTokenAddress); /** * @dev Emitted when a WETH address is remapped by a sovereign WETH address @@ -118,6 +118,7 @@ contract BridgeL2SovereignChain is gasTokenAddress = _gasTokenAddress; gasTokenNetwork = _gasTokenNetwork; gasTokenMetadata = _gasTokenMetadata; + // Set sovereign weth token or create new if not provided if (_sovereignWETHAddress == address(0)) { // Create a wrapped token for WETH, with salt == 0 @@ -185,12 +186,14 @@ contract BridgeL2SovereignChain is address[] memory sovereignTokenAddresses, bool[] memory isNotMintable ) external onlyBridgeManager { - require( - originNetworks.length == originTokenAddresses.length && - originTokenAddresses.length == sovereignTokenAddresses.length && - sovereignTokenAddresses.length == isNotMintable.length, - "Input array lengths mismatch" - ); + if ( + originNetworks.length != originTokenAddresses.length || + originNetworks.length != sovereignTokenAddresses.length || + originNetworks.length != isNotMintable.length + ) { + revert InputArraysLengthMismatch(); + } + // Make multiple calls to setSovereignTokenAddress for (uint256 i = 0; i < sovereignTokenAddresses.length; i++) { _setSovereignTokenAddress( @@ -229,7 +232,16 @@ contract BridgeL2SovereignChain is } /** - * @notice Function to remap sovereign address + * @notice Remap a wrapped token to a new sovereign token address + * @dev This function is used to allow any existing token to be mapped with + * origin token. + * @notice If this function is called multiple times for the same existingTokenAddress, + * this will override the previous calls and only keep the last sovereignTokenAddress. + * @notice The tokenInfoToWrappedToken mapping value is replaced by the new sovereign address but it's not the case for the wrappedTokenToTokenInfo map where the value is added, this way user will always be able to withdraw their tokens + * @param originNetwork Origin network + * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param sovereignTokenAddress Address of the sovereign wrapped token + * @param isNotMintable Flag to indicate if the wrapped token is not mintable */ function _setSovereignTokenAddress( uint32 originNetwork, @@ -248,6 +260,14 @@ contract BridgeL2SovereignChain is if (originNetwork == networkID) { revert OriginNetworkInvalid(); } + // Check if the token is already mapped + if ( + wrappedTokenToTokenInfo[sovereignTokenAddress].originTokenAddress != + address(0) + ) { + revert TokenAlreadyMapped(); + } + // Compute token info hash bytes32 tokenInfoHash = keccak256( abi.encodePacked(originNetwork, originTokenAddress) @@ -255,6 +275,7 @@ contract BridgeL2SovereignChain is // Set the address of the wrapper tokenInfoToWrappedToken[tokenInfoHash] = sovereignTokenAddress; // Set the token info mapping + // @note wrappedTokenToTokenInfo mapping is not overwritten while tokenInfoToWrappedToken it is wrappedTokenToTokenInfo[sovereignTokenAddress] = TokenInformation( originNetwork, originTokenAddress @@ -274,10 +295,10 @@ contract BridgeL2SovereignChain is * @notice Although the token is removed from the mapping, the user will still be able to withdraw their tokens using tokenInfoToWrappedToken mapping * @param sovereignTokenAddress Address of the sovereign wrapped token */ - function removeSovereignTokenAddress( + function removeLegacySovereignTokenAddress( address sovereignTokenAddress ) external onlyBridgeManager { - // Only allow to remove already mapped tokens + // Only allow to remove already remapped tokens TokenInformation memory tokenInfo = wrappedTokenToTokenInfo[ sovereignTokenAddress ]; @@ -292,11 +313,11 @@ contract BridgeL2SovereignChain is tokenInfoToWrappedToken[tokenInfoHash] == address(0) || tokenInfoToWrappedToken[tokenInfoHash] == sovereignTokenAddress ) { - revert TokenNotMapped(); + revert TokenNotRemapped(); } delete wrappedTokenToTokenInfo[sovereignTokenAddress]; delete wrappedAddressIsNotMintable[sovereignTokenAddress]; - emit RemoveSovereignTokenAddress(sovereignTokenAddress); + emit RemoveLegacySovereignTokenAddress(sovereignTokenAddress); } /** @@ -309,6 +330,9 @@ contract BridgeL2SovereignChain is address sovereignWETHTokenAddress, bool isNotMintable ) external onlyBridgeManager { + if (gasTokenAddress == address(0)) { + revert WETHRemappingNotSupportedOnGasTokenNetworks(); + } WETHToken = TokenWrapped(sovereignWETHTokenAddress); wrappedAddressIsNotMintable[sovereignWETHTokenAddress] = isNotMintable; emit SetSovereignWETHAddress(sovereignWETHTokenAddress, isNotMintable); @@ -411,4 +435,19 @@ contract BridgeL2SovereignChain is tokenWrapped.mint(destinationAddress, amount); } } + + // @note This function is not used in the current implementation. We overwrite it to improve deployed bytecode size + function activateEmergencyState() + external + override(IPolygonZkEVMBridgeV2, PolygonZkEVMBridgeV2) + { + revert NotValidBridgeManager(); + } + + function deactivateEmergencyState() + external + override(IPolygonZkEVMBridgeV2, PolygonZkEVMBridgeV2) + { + revert NotValidBridgeManager(); + } } diff --git a/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol index 5fb69e96d..d92e06258 100644 --- a/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol +++ b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol @@ -13,8 +13,8 @@ contract GlobalExitRootManagerL2SovereignChain is PolygonZkEVMGlobalExitRootL2, Initializable { - // aggOracleAddress address - address public aggOracleAddress; + // globalExitRootUpdater address + address public globalExitRootUpdater; // Inserted GER counter uint256 public insertedGERCount; @@ -29,13 +29,16 @@ contract GlobalExitRootManagerL2SovereignChain is */ event RemoveLastGlobalExitRoot(bytes32 indexed removedGlobalExitRoot); - modifier onlyAggOracleOrCoinbase() { - // Only allowed to be called by aggOracle or coinbase if aggOracle is zero - if ( - (aggOracleAddress == address(0) && block.coinbase != msg.sender) || - (aggOracleAddress != address(0) && aggOracleAddress != msg.sender) - ) { - revert OnlyAggOracleOrCoinbase(); + modifier onlyGlobalExitRootUpdater() { + // Only allowed to be called by GlobalExitRootUpdater or coinbase if GlobalExitRootUpdater is zero + if (globalExitRootUpdater == address(0)) { + if (block.coinbase != msg.sender) { + revert OnlyGlobalExitRootUpdater(); + } + } else { + if (globalExitRootUpdater != msg.sender) { + revert OnlyGlobalExitRootUpdater(); + } } _; } @@ -50,13 +53,13 @@ contract GlobalExitRootManagerL2SovereignChain is } /** - * @notice Initialize contract setting the aggOracleAddress + * @notice Initialize contract setting the globalExitRootUpdater */ function initialize( - address _aggOracleAddress + address _globalExitRootUpdater ) external virtual initializer { - // set aggOracleAddress - aggOracleAddress = _aggOracleAddress; + // set globalExitRootUpdater + globalExitRootUpdater = _globalExitRootUpdater; } /** @@ -65,7 +68,7 @@ contract GlobalExitRootManagerL2SovereignChain is */ function insertGlobalExitRoot( bytes32 _newRoot - ) external onlyAggOracleOrCoinbase { + ) external onlyGlobalExitRootUpdater { // do not insert GER if already set if (globalExitRootMap[_newRoot] == 0) { globalExitRootMap[_newRoot] = ++insertedGERCount; @@ -81,9 +84,10 @@ contract GlobalExitRootManagerL2SovereignChain is */ function removeLastGlobalExitRoots( bytes32[] calldata gersToRemove - ) external onlyAggOracleOrCoinbase { + ) external onlyGlobalExitRootUpdater { + uint256 insertedGERCountCache = insertedGERCount; // Can't remove if not enough roots have been inserted - if (gersToRemove.length > insertedGERCount) { + if (gersToRemove.length > insertedGERCountCache) { revert NotEnoughGlobalExitRootsInserted(); } // Iterate through the array of roots to remove them one by one @@ -92,12 +96,12 @@ contract GlobalExitRootManagerL2SovereignChain is // Check that the root to remove is the last inserted uint256 lastInsertedIndex = globalExitRootMap[rootToRemove]; - if (lastInsertedIndex != insertedGERCount) { + if (lastInsertedIndex != insertedGERCountCache) { revert NotLastInsertedGlobalExitRoot(); } // Remove from the mapping - delete globalExitRootMap[rootToRemove]; // Delete from the mapping + delete globalExitRootMap[rootToRemove]; // Decrement the counter insertedGERCount--; diff --git a/deployment/v2/1_createGenesis.ts b/deployment/v2/1_createGenesis.ts index d9fd2fe03..4a9178b98 100644 --- a/deployment/v2/1_createGenesis.ts +++ b/deployment/v2/1_createGenesis.ts @@ -90,7 +90,6 @@ async function main() { // Check if it's mainnet deployment const isMainnet = deployParameters["isMainnet"] === true ? true : false; - let isSovereignChain = deployParameters["isSovereignChain"] === true ? true : false; if (isMainnet === true) { timelockAdminAddress = mainnetMultisig; @@ -164,7 +163,7 @@ async function main() { } // Deploy implementation PolygonZkEVMBridge - const bridgeContractName = isSovereignChain ? "BridgeL2SovereignChain": "PolygonZkEVMBridgeV2"; + const bridgeContractName = "PolygonZkEVMBridgeV2"; const polygonZkEVMBridgeFactory = await ethers.getContractFactory(bridgeContractName, deployer); const deployTransactionBridge = (await polygonZkEVMBridgeFactory.getDeployTransaction()).data; // Mandatory to override the gasLimit since the estimation with create are mess up D: @@ -219,7 +218,7 @@ async function main() { /* *Deployment Global exit root manager */ - const globalExitRootContractName = isSovereignChain ? "GlobalExitRootManagerL2SovereignChain": "PolygonZkEVMGlobalExitRootL2"; + const globalExitRootContractName = "PolygonZkEVMGlobalExitRootL2"; const PolygonZkEVMGlobalExitRootL2Factory = await ethers.getContractFactory( globalExitRootContractName, deployer diff --git a/deployment/v2/4_createRollup.ts b/deployment/v2/4_createRollup.ts index b71de5f00..80c76f350 100644 --- a/deployment/v2/4_createRollup.ts +++ b/deployment/v2/4_createRollup.ts @@ -14,9 +14,10 @@ const pathGenesis = path.join(__dirname, "./genesis.json"); import {processorUtils, Constants} from "@0xpolygonhermez/zkevm-commonjs"; const createRollupParameters = require("./create_rollup_parameters.json"); -const genesis = require("./genesis.json"); +let genesis = require("./genesis.json"); const deployOutput = require("./deploy_output.json"); import "../helpers/utils"; +import updateVanillaGenesis from "./utils/updateVanillaGenesis"; const pathOutputJson = path.join(__dirname, "./create_rollup_output.json"); @@ -65,6 +66,8 @@ async function main() { adminZkEVM, forkID, consensusContract, + isVanillaClient, + sovereignParams, } = createRollupParameters; const supportedConsensus = ["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonPessimisticConsensus"]; @@ -73,16 +76,35 @@ async function main() { throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConsensus}`); } + // Check consensus compatibility + if (isVanillaClient) { + if (consensusContract !== "PolygonPessimisticConsensus") { + throw new Error(`Vanilla client only supports PolygonPessimisticConsensus`); + } + // Check sovereign params + const mandatorySovereignParams = [ + "bridgeManager", + "sovereignWETHAddress", + "sovereignWETHAddressIsNotMintable", + "globalExitRootUpdater", + ]; + for (const parameterName of mandatorySovereignParams) { + if (typeof sovereignParams[parameterName] === undefined || sovereignParams[parameterName] === "") { + throw new Error(`Missing sovereign parameter: ${parameterName}`); + } + } + } + const dataAvailabilityProtocol = createRollupParameters.dataAvailabilityProtocol || "PolygonDataCommittee"; - const supporteDataAvailabilityProtocols = ["PolygonDataCommittee"]; + const supportedDataAvailabilityProtocols = ["PolygonDataCommittee"]; if ( consensusContract.includes("PolygonValidiumEtrog") && - !supporteDataAvailabilityProtocols.includes(dataAvailabilityProtocol) + !supportedDataAvailabilityProtocols.includes(dataAvailabilityProtocol) ) { throw new Error( - `Data availability protocol not supported, supported data availability protocols are: ${supporteDataAvailabilityProtocols}` + `Data availability protocol not supported, supported data availability protocols are: ${supportedDataAvailabilityProtocols}` ); } @@ -346,72 +368,91 @@ async function main() { } } - let batchData; - if (consensusContract === "PolygonPessimisticConsensus") { - // Add the first batch of the created rollup - const newZKEVMContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonPessimisticConsensus; - - // Get last GER - const lastGER = await globalExitRootManagerContract.getLastGlobalExitRoot(); - - const dataInjectedTx = await polygonZkEVMBridgeContract.interface.encodeFunctionData("initialize", [ - rollupID, + let batchData = ""; + // If is vanilla client, replace genesis by sovereign contracts, else, inject initialization batch + if (isVanillaClient) { + const initializeParams = { + rollupID: rollupID, gasTokenAddress, gasTokenNetwork, - Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2, // Global exit root address on L2 - ethers.ZeroAddress, // Rollup manager on L2 does not exist - gasTokenMetadata as any, - ]); - - // check maximum length is 65535 - if ((dataInjectedTx.length - 2) / 2 > 0xffff) { - // throw error - throw new Error(`HugeTokenMetadataNotSupported`); - } - - const injectedTx = { - type: 0, // force ethers to parse it as a legacy transaction - chainId: 0, // force ethers to parse it as a pre-EIP155 transaction - to: await newZKEVMContract.bridgeAddress(), - value: 0, - gasPrice: 0, - gasLimit: 30000000, - nonce: 0, - data: dataInjectedTx, - signature: { - v: "0x1b", - r: "0x00000000000000000000000000000000000000000000000000000005ca1ab1e0", - s: "0x000000000000000000000000000000000000000000000000000000005ca1ab1e", - }, - }; - - // serialize transactions - const txObject = ethers.Transaction.from(injectedTx); - - const customData = processorUtils.rawTxToCustomRawTx(txObject.serialized); - batchData = { - batchL2Data: customData, - globalExitRoot: lastGER, - timestamp: blockDeploymentRollup.timestamp, - sequencer: trustedSequencer, - l1BlockNumber: blockDeploymentRollup.number, - l1BlockHash: blockDeploymentRollup.hash, - l1ParentHash: blockDeploymentRollup.parentHash, + globalExitRootManager: Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2, + polygonRollupManager: ethers.ZeroAddress, + gasTokenMetadata, + bridgeManager: sovereignParams.bridgeManager, + sovereignWETHAddress: sovereignParams.sovereignWETHAddress, + sovereignWETHAddressIsNotMintable: sovereignParams.sovereignWETHAddressIsNotMintable, + globalExitRootUpdater: sovereignParams.globalExitRootUpdater, }; + genesis = await updateVanillaGenesis(genesis, chainID, initializeParams); } else { - // Add the first batch of the created rollup - const newZKEVMContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonZkEVMEtrog; - batchData = { - batchL2Data: await newZKEVMContract.generateInitializeTransaction( + if (consensusContract === "PolygonPessimisticConsensus") { + // Add the first batch of the created rollup + const newZKEVMContract = (await PolygonconsensusFactory.attach( + newZKEVMAddress + )) as PolygonPessimisticConsensus; + + // Get last GER + const lastGER = await globalExitRootManagerContract.getLastGlobalExitRoot(); + + const dataInjectedTx = await polygonZkEVMBridgeContract.interface.encodeFunctionData("initialize", [ rollupID, gasTokenAddress, gasTokenNetwork, - gasTokenMetadata as any - ), - globalExitRoot: globalExitRoot, - timestamp: timestampReceipt, - sequencer: trustedSequencer, - }; + Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2, // Global exit root address on L2 + ethers.ZeroAddress, // Rollup manager on L2 does not exist + gasTokenMetadata as any, + ]); + + // check maximum length is 65535 + if ((dataInjectedTx.length - 2) / 2 > 0xffff) { + // throw error + throw new Error(`HugeTokenMetadataNotSupported`); + } + + const injectedTx = { + type: 0, // force ethers to parse it as a legacy transaction + chainId: 0, // force ethers to parse it as a pre-EIP155 transaction + to: await newZKEVMContract.bridgeAddress(), + value: 0, + gasPrice: 0, + gasLimit: 30000000, + nonce: 0, + data: dataInjectedTx, + signature: { + v: "0x1b", + r: "0x00000000000000000000000000000000000000000000000000000005ca1ab1e0", + s: "0x000000000000000000000000000000000000000000000000000000005ca1ab1e", + }, + }; + + // serialize transactions + const txObject = ethers.Transaction.from(injectedTx); + + const customData = processorUtils.rawTxToCustomRawTx(txObject.serialized); + batchData = { + batchL2Data: customData, + globalExitRoot: lastGER, + timestamp: blockDeploymentRollup.timestamp, + sequencer: trustedSequencer, + l1BlockNumber: blockDeploymentRollup.number, + l1BlockHash: blockDeploymentRollup.hash, + l1ParentHash: blockDeploymentRollup.parentHash, + }; + } else { + // Add the first batch of the created rollup + const newZKEVMContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonZkEVMEtrog; + batchData = { + batchL2Data: await newZKEVMContract.generateInitializeTransaction( + rollupID, + gasTokenAddress, + gasTokenNetwork, + gasTokenMetadata as any + ), + globalExitRoot: globalExitRoot, + timestamp: timestampReceipt, + sequencer: trustedSequencer, + }; + } } outputJson.firstBatchData = batchData; outputJson.genesis = genesis.root; @@ -420,6 +461,10 @@ async function main() { outputJson.verifierAddress = verifierContract.target; outputJson.consensusContract = consensusContract; + // Rewrite updated genesis in case of vanilla client + if (isVanillaClient) { + fs.writeFileSync(pathGenesis, JSON.stringify(genesis, null, 1)); + } fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); } diff --git a/deployment/v2/create_rollup_parameters.json.example b/deployment/v2/create_rollup_parameters.json.example index df6a8738d..f6926ebab 100644 --- a/deployment/v2/create_rollup_parameters.json.example +++ b/deployment/v2/create_rollup_parameters.json.example @@ -13,5 +13,12 @@ "deployerPvtKey": "", "maxFeePerGas":"", "maxPriorityFeePerGas":"", - "multiplierGas": "" + "multiplierGas": "", + "isVanillaClient": false, + "sovereignParams": { + "bridgeManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "sovereignWETHAddress": "0x0000000000000000000000000000000000000000", + "sovereignWETHAddressIsNotMintable": false, + "globalExitRootUpdater": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } } diff --git a/deployment/v2/deploy_parameters.json.example b/deployment/v2/deploy_parameters.json.example index 9794bd452..d57ad7c80 100644 --- a/deployment/v2/deploy_parameters.json.example +++ b/deployment/v2/deploy_parameters.json.example @@ -14,6 +14,5 @@ "deployerPvtKey": "", "maxFeePerGas":"", "maxPriorityFeePerGas":"", - "multiplierGas": "", - "isSovereignChain": false + "multiplierGas": "" } diff --git a/deployment/v2/utils/updateVanillaGenesis.ts b/deployment/v2/utils/updateVanillaGenesis.ts new file mode 100644 index 000000000..d6fb33133 --- /dev/null +++ b/deployment/v2/utils/updateVanillaGenesis.ts @@ -0,0 +1,219 @@ +import {MemDB, ZkEVMDB, getPoseidon, smtUtils, processorUtils} from "@0xpolygonhermez/zkevm-commonjs"; +import {ethers} from "hardhat"; +const {getContractAddress} = require("@ethersproject/address"); +const bridgeContractName = "BridgeL2SovereignChain"; +import {expect} from "chai"; + +async function updateVanillaGenesis(genesis, chainID, initializeParams) { + // Load genesis on a zkEVMDB + const poseidon = await getPoseidon(); + const {F} = poseidon; + const db = new MemDB(F); + const genesisRoot = [F.zero, F.zero, F.zero, F.zero]; + const accHashInput = [F.zero, F.zero, F.zero, F.zero]; + const zkEVMDB = await ZkEVMDB.newZkEVM( + db, + poseidon, + genesisRoot, + accHashInput, + genesis.genesis, + null, + null, + chainID + ); + const batch = await zkEVMDB.buildBatch( + 1000, //limitTimestamp + ethers.ZeroAddress, //trustedSequencer + smtUtils.stringToH4(ethers.ZeroHash), // l1InfoRoot + ); + // Add changeL2Block tx + const txChangeL2Block = { + type: 11, + deltaTimestamp: 3, + l1Info: { + globalExitRoot: "0x090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9", + blockHash: "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + timestamp: "42", + }, + indexL1InfoTree: 0, + }; + const rawChangeL2BlockTx = processorUtils.serializeChangeL2Block(txChangeL2Block); + batch.addRawTx(`0x${rawChangeL2BlockTx}`); + + // Create deploy bridge transaction + const sovereignBridgeFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + // Get deploy transaction for bridge + const deployBridgeData = await sovereignBridgeFactory.getDeployTransaction(); + const injectedTx = { + type: 0, // force ethers to parse it as a legacy transaction + chainId: 0, // force ethers to parse it as a pre-EIP155 transaction + to: null, + value: 0, + gasPrice: 0, + gasLimit: 30000000, + nonce: 0, + data: deployBridgeData.data, + signature: { + v: "0x1b", + r: "0x00000000000000000000000000000000000000000000000000000005ca1ab1e0", + s: "0x000000000000000000000000000000000000000000000000000000005ca1ab1e", + }, + }; + let txObject = ethers.Transaction.from(injectedTx); + const txDeployBridge = processorUtils.rawTxToCustomRawTx(txObject.serialized); + // Check ecrecover + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature)) + batch.addRawTx(txDeployBridge); + const sovereignBridgeAddress = getContractAddress({from: txObject.from, nonce: injectedTx.nonce}); + + // Create deploy GER transaction + const gerContractName = "GlobalExitRootManagerL2SovereignChain"; + const gerFactory = await ethers.getContractFactory(gerContractName); + const deployGERData = await gerFactory.getDeployTransaction(sovereignBridgeAddress); + injectedTx.data = deployGERData.data; + txObject = ethers.Transaction.from(injectedTx); + const txDeployGER = processorUtils.rawTxToCustomRawTx(txObject.serialized); + batch.addRawTx(txDeployGER); + const GERAddress = getContractAddress({from: txObject.from, nonce: injectedTx.nonce}); + + await batch.executeTxs(); + await zkEVMDB.consolidate(batch); + + // replace old bridge and ger manager by sovereign contracts bytecode + const oldBridge = genesis.genesis.find(function (obj) { + return obj.contractName == "PolygonZkEVMBridgeV2"; + }); + oldBridge.contractName = bridgeContractName; + oldBridge.bytecode = `0x${await zkEVMDB.getBytecode(sovereignBridgeAddress)}`; + + const oldGer = genesis.genesis.find(function (obj) { + return obj.contractName == "PolygonZkEVMGlobalExitRootL2"; + }); + oldGer.contractName = gerContractName; + oldGer.bytecode = `0x${await zkEVMDB.getBytecode(GERAddress)}`; + + // Setup a second zkEVM to initialize both contracts + const zkEVMDB2 = await ZkEVMDB.newZkEVM( + new MemDB(F), + poseidon, + genesisRoot, + accHashInput, + genesis.genesis, + null, + null, + chainID + ); + const batch2 = await zkEVMDB2.buildBatch( + 1000, //limitTimestamp + ethers.ZeroAddress, //trustedSequencer + smtUtils.stringToH4(ethers.ZeroHash), + undefined, + {} //options + ); + // Add changeL2Block tx + batch2.addRawTx(`0x${rawChangeL2BlockTx}`); + // Initialize bridge + const { + rollupID, + gasTokenAddress, + gasTokenNetwork, + globalExitRootManager, + polygonRollupManager, + gasTokenMetadata, + bridgeManager, + sovereignWETHAddress, + sovereignWETHAddressIsNotMintable, + globalExitRootUpdater, + } = initializeParams; + const initializeData = sovereignBridgeFactory.interface.encodeFunctionData( + "initialize(uint32,address,uint32,address,address,bytes,address,address,bool)", + [ + rollupID, + gasTokenAddress, + gasTokenNetwork, + globalExitRootManager, + polygonRollupManager, + gasTokenMetadata, + bridgeManager, + sovereignWETHAddress, + sovereignWETHAddressIsNotMintable, + ] + ); + // Get bridge proxy address + const bridgeProxy = genesis.genesis.find(function (obj) { + return obj.contractName == "PolygonZkEVMBridgeV2 proxy"; + }); + injectedTx.to = bridgeProxy.address; + injectedTx.data = initializeData; + txObject = ethers.Transaction.from(injectedTx); + const txInitializeBridge = processorUtils.rawTxToCustomRawTx(txObject.serialized); + batch2.addRawTx(txInitializeBridge); + + // Initialize GER Manager + const gerProxy = genesis.genesis.find(function (obj) { + return obj.contractName == "PolygonZkEVMGlobalExitRootL2 proxy"; + }); + const initializeGERData = gerFactory.interface.encodeFunctionData("initialize", [globalExitRootUpdater]); + // Update injectedTx to initialize GER + injectedTx.to = gerProxy.address; + injectedTx.data = initializeGERData; + + const txObject2 = ethers.Transaction.from(injectedTx); + const txInitializeGER = processorUtils.rawTxToCustomRawTx(txObject2.serialized); + batch2.addRawTx(txInitializeGER); + + // Execute batch + await batch2.executeTxs(); + await zkEVMDB2.consolidate(batch2); + + // Update bridgeProxy storage + bridgeProxy.contractName = bridgeContractName + " proxy"; + bridgeProxy.storage = await zkEVMDB2.dumpStorage(bridgeProxy.address); + // Pad storage values with zeros + const padTo32Bytes = (value) => { + const hexValue = value.startsWith("0x") ? value.slice(2) : value; // Remove '0x' + return "0x" + hexValue.padStart(64, "0"); // Pad to 64 hex digits + }; + bridgeProxy.storage = Object.entries(bridgeProxy.storage).reduce((acc, [key, value]) => { + acc[key] = padTo32Bytes(value); + return acc; + }, {}); + + // Sanity check bridge storage + if (rollupID !== 0) { + expect( + ethers.toBigInt(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000000"]) + ).to.equal(ethers.toBigInt(ethers.toBeHex(rollupID))); + } + if (gasTokenAddress !== ethers.ZeroAddress) { + expect( + ethers.toBigInt(bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006d"]) + ).to.equal( + ethers.toBigInt(`${ethers.toBeHex(gasTokenNetwork)}${gasTokenAddress.replace(/^0x/, "")}`.toLowerCase()) + ); + } + expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"]).to.include( + globalExitRootManager.toLowerCase().slice(2) + ); + expect(bridgeProxy.storage["0x00000000000000000000000000000000000000000000000000000000000000a3"]).to.include( + bridgeManager.toLowerCase().slice(2) + ); + + // Update bridgeProxy storage + gerProxy.contractName = gerContractName + " proxy"; + gerProxy.storage = await zkEVMDB2.dumpStorage(gerProxy.address); + gerProxy.storage = Object.entries(gerProxy.storage).reduce((acc, [key, value]) => { + acc[key] = padTo32Bytes(value); + return acc; + }, {}); + + // Sanity check ger storage + expect(gerProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000034"]).to.include( + globalExitRootUpdater.toLowerCase().slice(2) + ); + // update genesis root + genesis.root = smtUtils.h4toString(zkEVMDB2.getCurrentStateRoot()); + return genesis; +} + +export default updateVanillaGenesis; diff --git a/docker/scripts/v2/deploy-dockerv2.sh b/docker/scripts/v2/deploy-dockerv2.sh index 40f2b03dc..c27a95f0f 100755 --- a/docker/scripts/v2/deploy-dockerv2.sh +++ b/docker/scripts/v2/deploy-dockerv2.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -e sudo rm -rf docker/gethData/geth_data sudo DEV_PERIOD=1 docker compose -f docker/docker-compose.yml up -d geth sleep 5 @@ -6,6 +7,7 @@ node docker/scripts/fund-accounts.js cp docker/scripts/v2/deploy_parameters_docker.json deployment/v2/deploy_parameters.json cp docker/scripts/v2/create_rollup_parameters_docker.json deployment/v2/create_rollup_parameters.json npm run deploy:testnet:v2:localhost +rm -rf docker/deploymentOutput mkdir docker/deploymentOutput sudo mv deployment/v2/deploy_output.json docker/deploymentOutput sudo mv deployment/v2/genesis.json docker/deploymentOutput diff --git a/hardhat.config.ts b/hardhat.config.ts index c41a38d42..9c4bb60cd 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -80,7 +80,7 @@ const config: HardhatUserConfig = { settings: { optimizer: { enabled: true, - runs: 0, + runs: 20, }, evmVersion: "shanghai", }, // try yul optimizer diff --git a/package-lock.json b/package-lock.json index 9f3770680..ec3103468 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7010,9 +7010,9 @@ } }, "node_modules/ethers": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.3.tgz", - "integrity": "sha512-/DzbZOLVtoO4fKvvQwpEucHAQgIwBGWuRvBdwE/lMXgXvvHHTSkn7XqAQ2b+gjJzZDJjWA9OD05bVceVOsBHbg==", + "version": "6.13.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.4.tgz", + "integrity": "sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==", "dev": true, "funding": [ { @@ -7029,26 +7029,19 @@ "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", - "@types/node": "18.15.13", + "@types/node": "22.7.5", "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", + "tslib": "2.7.0", "ws": "8.17.1" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", - "dev": true, - "peer": true - }, "node_modules/ethers/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true, "peer": true }, diff --git a/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts b/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts index 1013ec9f2..8f4bc6ab7 100644 --- a/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts +++ b/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts @@ -263,32 +263,6 @@ describe("SovereignChainBridge Gas tokens tests", () => { expect(await sovereignChainBridgeContract.gasTokenMetadata()).to.be.equal(gasTokenMetadata); }); - it("should check the emergency state", async () => { - expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(false); - - await expect(sovereignChainBridgeContract.activateEmergencyState()).to.be.revertedWithCustomError( - sovereignChainBridgeContract, - "OnlyRollupManager" - ); - await expect(sovereignChainBridgeContract.connect(rollupManager).activateEmergencyState()).to.emit( - sovereignChainBridgeContract, - "EmergencyStateActivated" - ); - - expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(true); - - await expect( - sovereignChainBridgeContract.connect(deployer).deactivateEmergencyState() - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyRollupManager"); - - await expect(sovereignChainBridgeContract.connect(rollupManager).deactivateEmergencyState()).to.emit( - sovereignChainBridgeContract, - "EmergencyStateDeactivated" - ); - - expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(false); - }); - it("should SovereignChain bridge asset and verify merkle proof", async () => { const depositCount = await sovereignChainBridgeContract.depositCount(); const originNetwork = networkIDRollup2; diff --git a/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts b/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts index ee44f4d37..96b83cecc 100644 --- a/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts +++ b/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts @@ -31,7 +31,7 @@ describe("SovereignChainBridge Gas tokens tests", () => { let sovereignChainBridgeContract: BridgeL2SovereignChain; let polTokenContract: ERC20PermitMock; - let sovereignChainGlobalExitRoot: GlobalExitRootManagerL2SovereignChain; + let sovereignChainGlobalExitRootContract: GlobalExitRootManagerL2SovereignChain; let deployer: any; let rollupManager: any; @@ -72,12 +72,18 @@ describe("SovereignChainBridge Gas tokens tests", () => { })) as unknown as BridgeL2SovereignChain; // deploy global exit root manager - const SovereignChainGlobalExitRootFactory = await ethers.getContractFactory( + const GlobalExitRootManagerL2SovereignChainFactory = await ethers.getContractFactory( "GlobalExitRootManagerL2SovereignChain" ); - sovereignChainGlobalExitRoot = await SovereignChainGlobalExitRootFactory.deploy( - sovereignChainBridgeContract.target - ); + sovereignChainGlobalExitRootContract = (await upgrades.deployProxy( + GlobalExitRootManagerL2SovereignChainFactory, + [deployer.address], // Initializer params + { + initializer: "initialize", // initializer function name + constructorArgs: [sovereignChainBridgeContract.target], // Constructor arguments + unsafeAllow: ["constructor", "state-variable-immutable"], + } + )) as unknown as GlobalExitRootManagerL2SovereignChain; // deploy token const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); @@ -96,7 +102,7 @@ describe("SovereignChainBridge Gas tokens tests", () => { networkIDRollup2, polTokenContract.target, // zero for ether 0, // zero for ether - sovereignChainGlobalExitRoot.target, + sovereignChainGlobalExitRootContract.target, rollupManager.address, metadataToken, ethers.Typed.address(bridgeManager.address), @@ -172,20 +178,26 @@ describe("SovereignChainBridge Gas tokens tests", () => { // add rollup Merkle root await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); - await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); // check roots - const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); expect(rollupExitRootSC).to.be.equal(rollupRoot); const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Try to insert global exit root with non coinbase + await expect( + sovereignChainGlobalExitRootContract.connect(acc1).insertGlobalExitRoot(computedGlobalExitRoot) + ).to.be.revertedWithCustomError(sovereignChainGlobalExitRootContract, "OnlyGlobalExitRootUpdater"); + // Insert global exit root - expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) - .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") .withArgs(computedGlobalExitRoot); // Check GER has value in mapping - expect(await sovereignChainGlobalExitRoot.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); // check merkle proof const index = 0; const proofLocal = merkleTree.getProofTreeByIndex(0); @@ -266,7 +278,7 @@ describe("SovereignChainBridge Gas tokens tests", () => { it("should check the constructor parameters", async () => { expect(await sovereignChainBridgeContract.globalExitRootManager()).to.be.equal( - sovereignChainGlobalExitRoot.target + sovereignChainGlobalExitRootContract.target ); expect(await sovereignChainBridgeContract.networkID()).to.be.equal(networkIDRollup2); expect(await sovereignChainBridgeContract.polygonRollupManager()).to.be.equal(rollupManager.address); @@ -276,32 +288,6 @@ describe("SovereignChainBridge Gas tokens tests", () => { expect(await sovereignChainBridgeContract.gasTokenMetadata()).to.be.equal(gasTokenMetadata); }); - it("should check the emergency state", async () => { - expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(false); - - await expect(sovereignChainBridgeContract.activateEmergencyState()).to.be.revertedWithCustomError( - sovereignChainBridgeContract, - "OnlyRollupManager" - ); - await expect(sovereignChainBridgeContract.connect(rollupManager).activateEmergencyState()).to.emit( - sovereignChainBridgeContract, - "EmergencyStateActivated" - ); - - expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(true); - - await expect( - sovereignChainBridgeContract.connect(deployer).deactivateEmergencyState() - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyRollupManager"); - - await expect(sovereignChainBridgeContract.connect(rollupManager).deactivateEmergencyState()).to.emit( - sovereignChainBridgeContract, - "EmergencyStateDeactivated" - ); - - expect(await sovereignChainBridgeContract.isEmergencyState()).to.be.equal(false); - }); - it("should SovereignChain bridge asset and verify merkle proof", async () => { const depositCount = await sovereignChainBridgeContract.depositCount(); const originNetwork = networkIDRollup2; @@ -699,8 +685,8 @@ describe("SovereignChainBridge Gas tokens tests", () => { } const rootRollup = merkleTreeRollup.getRoot(); // check only rollup account with update rollup exit root - await expect(sovereignChainGlobalExitRoot.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( - sovereignChainGlobalExitRoot, + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, "OnlyAllowedContracts" ); @@ -708,10 +694,10 @@ describe("SovereignChainBridge Gas tokens tests", () => { await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); - await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); // check roots - const sovereignChainExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + const sovereignChainExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); expect(sovereignChainExitRootSC).to.be.equal(rootRollup); const mainnetExitRootSC = ethers.ZeroHash; expect(mainnetExitRootSC).to.be.equal(mainnetExitRoot); @@ -719,8 +705,8 @@ describe("SovereignChainBridge Gas tokens tests", () => { const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rootRollup); // Insert global exit root - expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) - .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") .withArgs(computedGlobalExitRoot); // check merkle proof @@ -844,25 +830,25 @@ describe("SovereignChainBridge Gas tokens tests", () => { const rootRollup = merkleTreeRollup.getRoot(); // check only rollup account with update rollup exit root - await expect(sovereignChainGlobalExitRoot.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( - sovereignChainGlobalExitRoot, + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, "OnlyAllowedContracts" ); // add rollup Merkle root await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); - await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); // check roots - const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); expect(rollupExitRootSC).to.be.equal(rootRollup); const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); // Insert global exit root - expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) - .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") .withArgs(computedGlobalExitRoot); // check merkle proof @@ -1001,7 +987,7 @@ describe("SovereignChainBridge Gas tokens tests", () => { const wrappedTokenAddress = newWrappedToken.target; const newDestinationNetwork = networkIDRollup; - const rollupExitRoot = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); // create a new deposit await expect(newWrappedToken.approve(sovereignChainBridgeContract.target, amount)) @@ -1244,16 +1230,16 @@ describe("SovereignChainBridge Gas tokens tests", () => { // add rollup Merkle root await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); - await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); // check roots - const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); expect(rollupExitRootSC).to.be.equal(rollupRoot); const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); // Insert global exit root - expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) - .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") .withArgs(computedGlobalExitRoot); // check merkle proof @@ -1393,16 +1379,16 @@ describe("SovereignChainBridge Gas tokens tests", () => { // add rollup Merkle root await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); - await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); // check roots - const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); expect(rollupExitRootSC).to.be.equal(rollupRoot); const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); // Insert global exit root - expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) - .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") .withArgs(computedGlobalExitRoot); // check merkle proof @@ -1496,17 +1482,17 @@ describe("SovereignChainBridge Gas tokens tests", () => { // add rollup Merkle root await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); - await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); // check roots - const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); expect(rollupExitRootSC).to.be.equal(rollupRoot); const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); // Insert global exit root - expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) - .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") .withArgs(computedGlobalExitRoot); // check merkle proof const index = 0; diff --git a/test/contractsv2/BridgeL2SovereignChain.test.ts b/test/contractsv2/BridgeL2SovereignChain.test.ts index fcf46b730..c2167dac8 100644 --- a/test/contractsv2/BridgeL2SovereignChain.test.ts +++ b/test/contractsv2/BridgeL2SovereignChain.test.ts @@ -63,12 +63,12 @@ describe("BridgeL2SovereignChain Contract", () => { })) as unknown as BridgeL2SovereignChain; // deploy global exit root manager - const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory( + const GlobalExitRootManagerL2SovereignChainFactory = await ethers.getContractFactory( "GlobalExitRootManagerL2SovereignChain" ); sovereignChainGlobalExitRootContract = (await upgrades.deployProxy( - PolygonZkEVMGlobalExitRootFactory, - [deployer.address], // Initializer params + GlobalExitRootManagerL2SovereignChainFactory, + [ethers.ZeroAddress], // Initializer params { initializer: "initialize", // initializer function name constructorArgs: [sovereignChainBridgeContract.target], // Constructor arguments @@ -185,6 +185,11 @@ describe("BridgeL2SovereignChain Contract", () => { await sovereignChainBridgeContract .connect(bridgeManager) .setSovereignTokenAddress(networkIDRollup1, polTokenContract.target, legacyToken.target, true); + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setSovereignTokenAddress(networkIDRollup1, polTokenContract.target, legacyToken.target, true) + ).to.revertedWithCustomError(sovereignChainBridgeContract, "TokenAlreadyMapped"); // Deploy token 2 const updatedToken = await tokenFactory.deploy(tokenName, tokenSymbol, deployer.address, iBalance); // Send legacy tokens to bridge @@ -339,7 +344,7 @@ describe("BridgeL2SovereignChain Contract", () => { // Try to insert global exit root with non coinbase await expect( sovereignChainGlobalExitRootContract.connect(acc1).insertGlobalExitRoot(computedGlobalExitRoot) - ).to.be.revertedWithCustomError(sovereignChainGlobalExitRootContract, "OnlyAggOracleOrCoinbase"); + ).to.be.revertedWithCustomError(sovereignChainGlobalExitRootContract, "OnlyGlobalExitRootUpdater"); // Insert global exit root expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) @@ -384,12 +389,12 @@ describe("BridgeL2SovereignChain Contract", () => { // Remove unmapped sovereign token address, should revert await expect( - sovereignChainBridgeContract.connect(bridgeManager).removeSovereignTokenAddress(tokenAddress) - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotMapped"); + sovereignChainBridgeContract.connect(bridgeManager).removeLegacySovereignTokenAddress(tokenAddress) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotRemapped"); // Remove not updated sovereign token address, should revert await expect( - sovereignChainBridgeContract.connect(bridgeManager).removeSovereignTokenAddress(sovereignToken.target) - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotMapped"); + sovereignChainBridgeContract.connect(bridgeManager).removeLegacySovereignTokenAddress(sovereignToken.target) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotRemapped"); // Remove updated sovereign token address // Remap token a second time to support removal function @@ -401,9 +406,9 @@ describe("BridgeL2SovereignChain Contract", () => { .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") .withArgs(networkIDRollup, tokenAddress, sovereignToken2.target, true); await expect( - sovereignChainBridgeContract.connect(bridgeManager).removeSovereignTokenAddress(sovereignToken.target) + sovereignChainBridgeContract.connect(bridgeManager).removeLegacySovereignTokenAddress(sovereignToken.target) ) - .to.emit(sovereignChainBridgeContract, "RemoveSovereignTokenAddress") + .to.emit(sovereignChainBridgeContract, "RemoveLegacySovereignTokenAddress") .withArgs(sovereignToken.target); // Remap sovereign address with multiCall const originNetworksArray = [networkIDRollup, networkIDRollup]; @@ -424,6 +429,15 @@ describe("BridgeL2SovereignChain Contract", () => { .withArgs(networkIDRollup, tokenAddress, sovereignToken3.target, true) .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") .withArgs(networkIDRollup, tokenAddress2.target, sovereignToken4.target, false); + + await expect( + sovereignChainBridgeContract.connect(bridgeManager).setMultipleSovereignTokenAddress( + originNetworksArray, + [], // Different length + sovereignTokenAddressesArray, + isNotMintableArray + ) + ).to.revertedWithCustomError(sovereignChainBridgeContract, "InputArraysLengthMismatch"); }); it("should Sovereign Chain bridge a remapped asset mintable and verify merkle proof", async () => { @@ -586,6 +600,10 @@ describe("BridgeL2SovereignChain Contract", () => { await expect( sovereignChainBridgeContract.bridgeMessageWETH(networkIDMainnet, deployer.address, 0, true, "0x") ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NativeTokenIsEther"); + + await expect( + sovereignChainBridgeContract.connect(bridgeManager).setSovereignWETHAddress(deployer.address, true) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "WETHRemappingNotSupportedOnGasTokenNetworks"); }); it("should Sovereign Chain bridge asset and verify merkle proof", async () => { @@ -2131,71 +2149,12 @@ describe("BridgeL2SovereignChain Contract", () => { it("should test emergency state", async () => { await expect(sovereignChainBridgeContract.activateEmergencyState()).to.be.revertedWithCustomError( sovereignChainBridgeContract, - "OnlyRollupManager" + "NotValidBridgeManager" ); - await expect(sovereignChainBridgeContract.connect(rollupManager).activateEmergencyState()).to.emit( + await expect(sovereignChainBridgeContract.deactivateEmergencyState()).to.be.revertedWithCustomError( sovereignChainBridgeContract, - "EmergencyStateActivated" + "NotValidBridgeManager" ); - - const tokenAddress = polTokenContract.target; - const amount = ethers.parseEther("10"); - const destinationNetwork = networkIDRollup; - const destinationAddress = deployer.address; - - const metadata = metadataToken; - - await expect( - sovereignChainBridgeContract.bridgeAsset( - destinationNetwork, - destinationAddress, - amount, - tokenAddress, - true, - "0x" - ) - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); - - await expect( - sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, "0x") - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); - - await expect( - sovereignChainBridgeContract.bridgeMessageWETH(destinationNetwork, destinationAddress, amount, true, "0x") - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); - - const mockMerkleProof = new Array(32).fill(ethers.ZeroHash) as any; - await expect( - sovereignChainBridgeContract.claimAsset( - mockMerkleProof, - mockMerkleProof, - ethers.ZeroHash, - ethers.ZeroHash, - ethers.ZeroHash, - 0, - tokenAddress, - destinationNetwork, - destinationAddress, - amount, - metadata - ) - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); - - await expect( - sovereignChainBridgeContract.claimMessage( - mockMerkleProof, - mockMerkleProof, - ethers.ZeroHash, - ethers.ZeroHash, - ethers.ZeroHash, - 0, - tokenAddress, - destinationNetwork, - destinationAddress, - amount, - metadata - ) - ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyNotEmergencyState"); }); }); From 8f5e753429159e88c3ab329dbf8054b274429de7 Mon Sep 17 00:00:00 2001 From: Ignasi Date: Tue, 22 Oct 2024 16:49:27 +0200 Subject: [PATCH 4/8] Add weth at genesis + other review improvements --- deployment/v2/utils/deployment-utils.ts | 8 +++ deployment/v2/utils/updateVanillaGenesis.ts | 69 ++++++++++++++----- .../v2/create_rollup_parameters_docker.json | 11 ++- 3 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 deployment/v2/utils/deployment-utils.ts diff --git a/deployment/v2/utils/deployment-utils.ts b/deployment/v2/utils/deployment-utils.ts new file mode 100644 index 000000000..63c473ba8 --- /dev/null +++ b/deployment/v2/utils/deployment-utils.ts @@ -0,0 +1,8 @@ +const padTo32Bytes = (value) => { + const hexValue = value.startsWith("0x") ? value.slice(2) : value; // Remove '0x' + return "0x" + hexValue.padStart(64, "0"); // Pad to 64 hex digits +}; + +export { + padTo32Bytes +} \ No newline at end of file diff --git a/deployment/v2/utils/updateVanillaGenesis.ts b/deployment/v2/utils/updateVanillaGenesis.ts index d6fb33133..cd41d3c58 100644 --- a/deployment/v2/utils/updateVanillaGenesis.ts +++ b/deployment/v2/utils/updateVanillaGenesis.ts @@ -3,7 +3,7 @@ import {ethers} from "hardhat"; const {getContractAddress} = require("@ethersproject/address"); const bridgeContractName = "BridgeL2SovereignChain"; import {expect} from "chai"; - +import {padTo32Bytes} from "./deployment-utils"; async function updateVanillaGenesis(genesis, chainID, initializeParams) { // Load genesis on a zkEVMDB const poseidon = await getPoseidon(); @@ -24,11 +24,11 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { const batch = await zkEVMDB.buildBatch( 1000, //limitTimestamp ethers.ZeroAddress, //trustedSequencer - smtUtils.stringToH4(ethers.ZeroHash), // l1InfoRoot + smtUtils.stringToH4(ethers.ZeroHash) // l1InfoRoot ); // Add changeL2Block tx const txChangeL2Block = { - type: 11, + type: 11, deltaTimestamp: 3, l1Info: { globalExitRoot: "0x090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9", @@ -62,17 +62,22 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { let txObject = ethers.Transaction.from(injectedTx); const txDeployBridge = processorUtils.rawTxToCustomRawTx(txObject.serialized); // Check ecrecover - expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature)) + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature)); batch.addRawTx(txDeployBridge); const sovereignBridgeAddress = getContractAddress({from: txObject.from, nonce: injectedTx.nonce}); // Create deploy GER transaction const gerContractName = "GlobalExitRootManagerL2SovereignChain"; const gerFactory = await ethers.getContractFactory(gerContractName); - const deployGERData = await gerFactory.getDeployTransaction(sovereignBridgeAddress); + const oldBridge = genesis.genesis.find(function (obj) { + return obj.contractName == "PolygonZkEVMBridgeV2"; + }); + const deployGERData = await gerFactory.getDeployTransaction(oldBridge.address); injectedTx.data = deployGERData.data; txObject = ethers.Transaction.from(injectedTx); const txDeployGER = processorUtils.rawTxToCustomRawTx(txObject.serialized); + // Check ecrecover + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature)); batch.addRawTx(txDeployGER); const GERAddress = getContractAddress({from: txObject.from, nonce: injectedTx.nonce}); @@ -80,9 +85,6 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { await zkEVMDB.consolidate(batch); // replace old bridge and ger manager by sovereign contracts bytecode - const oldBridge = genesis.genesis.find(function (obj) { - return obj.contractName == "PolygonZkEVMBridgeV2"; - }); oldBridge.contractName = bridgeContractName; oldBridge.bytecode = `0x${await zkEVMDB.getBytecode(sovereignBridgeAddress)}`; @@ -106,9 +108,7 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { const batch2 = await zkEVMDB2.buildBatch( 1000, //limitTimestamp ethers.ZeroAddress, //trustedSequencer - smtUtils.stringToH4(ethers.ZeroHash), - undefined, - {} //options + smtUtils.stringToH4(ethers.ZeroHash) // l1InfoRoot ); // Add changeL2Block tx batch2.addRawTx(`0x${rawChangeL2BlockTx}`); @@ -147,6 +147,8 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { injectedTx.data = initializeData; txObject = ethers.Transaction.from(injectedTx); const txInitializeBridge = processorUtils.rawTxToCustomRawTx(txObject.serialized); + // Check ecrecover + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature)); batch2.addRawTx(txInitializeBridge); // Initialize GER Manager @@ -160,6 +162,8 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { const txObject2 = ethers.Transaction.from(injectedTx); const txInitializeGER = processorUtils.rawTxToCustomRawTx(txObject2.serialized); + // Check ecrecover + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature)); batch2.addRawTx(txInitializeGER); // Execute batch @@ -169,11 +173,25 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { // Update bridgeProxy storage bridgeProxy.contractName = bridgeContractName + " proxy"; bridgeProxy.storage = await zkEVMDB2.dumpStorage(bridgeProxy.address); + // If bridge initialized with a zero sovereign weth address and a non zero gas token, we should add created erc20 weth contract to the genesis + if (gasTokenAddress !== ethers.ZeroAddress && sovereignWETHAddress === ethers.ZeroAddress) { + const wethAddress = bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"]; + const wethGenesis = { + contractName: "WETH", + balance: "0", + nonce: "1", + address: wethAddress, + bytecode: `0x${await zkEVMDB2.getBytecode(wethAddress)}`, + }; + const wethStorage = await zkEVMDB2.dumpStorage(wethAddress); + wethGenesis.storage = Object.entries(wethStorage).reduce((acc, [key, value]) => { + acc[key] = padTo32Bytes(value); + return acc; + }, {}); + genesis.genesis.push(wethGenesis); + } + // Pad storage values with zeros - const padTo32Bytes = (value) => { - const hexValue = value.startsWith("0x") ? value.slice(2) : value; // Remove '0x' - return "0x" + hexValue.padStart(64, "0"); // Pad to 64 hex digits - }; bridgeProxy.storage = Object.entries(bridgeProxy.storage).reduce((acc, [key, value]) => { acc[key] = padTo32Bytes(value); return acc; @@ -181,9 +199,13 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { // Sanity check bridge storage if (rollupID !== 0) { + // RollupID value is stored at position 68 with globalExitRootManager address. Slice from byte 2 to 2-8 to get the rollupID expect( - ethers.toBigInt(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000000"]) - ).to.equal(ethers.toBigInt(ethers.toBeHex(rollupID))); + bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"].slice( + 2 + 54, + 2 + 54 + 8 + ) + ).to.include(rollupID.toString(16)); } if (gasTokenAddress !== ethers.ZeroAddress) { expect( @@ -192,6 +214,16 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { ethers.toBigInt(`${ethers.toBeHex(gasTokenNetwork)}${gasTokenAddress.replace(/^0x/, "")}`.toLowerCase()) ); } + if (sovereignWETHAddress !== ethers.ZeroAddress) { + expect(bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"]).to.include( + sovereignWETHAddress.toLowerCase().slice(2) + ); + } + if (sovereignWETHAddressIsNotMintable) { + expect(bridgeProxy.storage["0xc7edf51165adec508a5250d96d0588939529f9442a12e2ffa25d7692caac0ef0"]).to.equal( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ); + } expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"]).to.include( globalExitRootManager.toLowerCase().slice(2) ); @@ -199,6 +231,9 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { bridgeManager.toLowerCase().slice(2) ); + // Check bridgeAddress is included in ger bytecode + expect(oldGer.bytecode).to.include(oldBridge.address.toLowerCase().slice(2)); + // Update bridgeProxy storage gerProxy.contractName = gerContractName + " proxy"; gerProxy.storage = await zkEVMDB2.dumpStorage(gerProxy.address); diff --git a/docker/scripts/v2/create_rollup_parameters_docker.json b/docker/scripts/v2/create_rollup_parameters_docker.json index f952ca9ed..e3de619a0 100644 --- a/docker/scripts/v2/create_rollup_parameters_docker.json +++ b/docker/scripts/v2/create_rollup_parameters_docker.json @@ -8,10 +8,17 @@ "adminZkEVM": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "forkID": 11, "consensusContract": "PolygonPessimisticConsensus", - "gasTokenAddress": "", + "gasTokenAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "deployerPvtKey": "", "maxFeePerGas": "", "maxPriorityFeePerGas": "", "multiplierGas": "", - "programVKey": "0xac51a6a2e513d02e4f39ea51d4d133cec200b940805f1054eabbb6d6412c959f" + "programVKey": "0xac51a6a2e513d02e4f39ea51d4d133cec200b940805f1054eabbb6d6412c959f", + "isVanillaClient": false, + "sovereignParams": { + "bridgeManager": "0xC7899Ff6A3aC2FF59261bD960A8C880DF06E1041", + "sovereignWETHAddress": "0x0000000000000000000000000000000000000000", + "sovereignWETHAddressIsNotMintable": false, + "globalExitRootUpdater": "0xB55B27Cca633A73108893985350bc26B8A00C43a" + } } \ No newline at end of file From 2a3ebd7be98a19166c9d4ff40c9588c6ee01b68e Mon Sep 17 00:00:00 2001 From: Ignasi Date: Thu, 24 Oct 2024 13:11:37 +0200 Subject: [PATCH 5/8] Improve WETH comments at bridge contract --- contracts/v2/PolygonZkEVMBridgeV2.sol | 3 ++- docker/scripts/v2/deploy-dockerv2.sh | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/contracts/v2/PolygonZkEVMBridgeV2.sol b/contracts/v2/PolygonZkEVMBridgeV2.sol index 4a705c313..cbd88c92d 100644 --- a/contracts/v2/PolygonZkEVMBridgeV2.sol +++ b/contracts/v2/PolygonZkEVMBridgeV2.sol @@ -89,6 +89,7 @@ contract PolygonZkEVMBridgeV2 is bytes public gasTokenMetadata; // WETH address + // @note If WETH address is zero, means the gasToken of the network is ether, else means the network has a custom erc20 gas token. This value is set at initialization of the contract. In case gasTokenAddress != zero, a erc20 contract is deployed and the created address is set as WETH address, to handle wrapped ether TokenWrapped public WETHToken; /** @@ -442,7 +443,7 @@ contract PolygonZkEVMBridgeV2 is * @param mainnetExitRoot Mainnet exit root * @param rollupExitRoot Rollup exit root * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param destinationNetwork Network destination * @param destinationAddress Address destination * @param amount Amount of tokens diff --git a/docker/scripts/v2/deploy-dockerv2.sh b/docker/scripts/v2/deploy-dockerv2.sh index c27a95f0f..0b5b3c935 100755 --- a/docker/scripts/v2/deploy-dockerv2.sh +++ b/docker/scripts/v2/deploy-dockerv2.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -sudo rm -rf docker/gethData/geth_data -sudo DEV_PERIOD=1 docker compose -f docker/docker-compose.yml up -d geth +rm -rf docker/gethData/geth_data +DEV_PERIOD=1 docker compose -f docker/docker-compose.yml up -d geth sleep 5 node docker/scripts/fund-accounts.js cp docker/scripts/v2/deploy_parameters_docker.json deployment/v2/deploy_parameters.json @@ -9,10 +9,10 @@ cp docker/scripts/v2/create_rollup_parameters_docker.json deployment/v2/create_r npm run deploy:testnet:v2:localhost rm -rf docker/deploymentOutput mkdir docker/deploymentOutput -sudo mv deployment/v2/deploy_output.json docker/deploymentOutput -sudo mv deployment/v2/genesis.json docker/deploymentOutput -sudo mv deployment/v2/create_rollup_output.json docker/deploymentOutput -sudo DEV_PERIOD=1 docker compose -f docker/docker-compose.yml down -sudo docker build -t hermeznetwork/geth-zkevm-contracts -f docker/Dockerfile . +mv deployment/v2/deploy_output.json docker/deploymentOutput +mv deployment/v2/genesis.json docker/deploymentOutput +mv deployment/v2/create_rollup_output.json docker/deploymentOutput +DEV_PERIOD=1 docker compose -f docker/docker-compose.yml down +docker build -t hermeznetwork/geth-zkevm-contracts -f docker/Dockerfile . # Let it readable for the multiplatform build coming later! -sudo chmod -R go+rxw docker/gethData \ No newline at end of file +chmod -R go+rxw docker/gethData \ No newline at end of file From 29023ea5265b293057a5712fa4836a24c37e9b93 Mon Sep 17 00:00:00 2001 From: Ignasi Date: Thu, 24 Oct 2024 15:43:30 +0200 Subject: [PATCH 6/8] typos --- upgrade/upgradePessimistic/upgradePessimistic.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/upgrade/upgradePessimistic/upgradePessimistic.ts b/upgrade/upgradePessimistic/upgradePessimistic.ts index 8157cb1a7..fe156df1b 100644 --- a/upgrade/upgradePessimistic/upgradePessimistic.ts +++ b/upgrade/upgradePessimistic/upgradePessimistic.ts @@ -18,7 +18,7 @@ async function main() { /* * Check upgrade parameters - * Check that every necessary parameter is fullfilled + * Check that every necessary parameter is fulfilled */ const mandatoryUpgradeParameters = ["rollupManagerAddress", "timelockDelay"]; @@ -39,7 +39,7 @@ async function main() { const bridgeAddress = await polygonRMContract.bridgeAddress(); // Load provider - let currentProvider = ethers.provider; + const currentProvider = ethers.provider; if (upgradeParameters.multiplierGas || upgradeParameters.maxFeePerGas) { if (process.env.HARDHAT_NETWORK !== "hardhat") { currentProvider = ethers.getDefaultProvider( @@ -96,7 +96,7 @@ async function main() { // load timelock const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock", deployer); - // prapare upgrades + // prepare upgrades // Upgrade to rollup manager const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager"); @@ -125,8 +125,8 @@ async function main() { const operationRollupManager = genOperation( proxyAdmin.target, 0, // value - proxyAdmin.interface.encodeFunctionData("upgrade", [rollupManagerAddress, implRollupManager]), - ethers.ZeroHash, // predecesoor + proxyAdmin.interface.encodeFunctionData("upgrade", [rollupManagerAddress, implRollupManager]), // data + ethers.ZeroHash, // predecessor salt // salt ); @@ -135,7 +135,7 @@ async function main() { operationRollupManager.target, operationRollupManager.value, operationRollupManager.data, - ethers.ZeroHash, // predecesoor + ethers.ZeroHash, // predecessor salt, // salt timelockDelay, ]); @@ -145,7 +145,7 @@ async function main() { operationRollupManager.target, operationRollupManager.value, operationRollupManager.data, - ethers.ZeroHash, // predecesoor + ethers.ZeroHash, // predecessor salt, // salt ]); @@ -155,7 +155,7 @@ async function main() { const outputJson = { scheduleData, executeData, - timelockContractAdress: timelockAddress, + timelockContractAddress: timelockAddress, }; fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); } From f1227e4431a5097a89776c316e0d2e8759df8e8e Mon Sep 17 00:00:00 2001 From: Ignasi Date: Tue, 29 Oct 2024 10:07:03 +0100 Subject: [PATCH 7/8] Review fixes Package-lock Small fix upgrade rollupManager pessimistic script --- contracts/v2/PolygonZkEVMBridgeV2.sol | 7 +- .../BridgeL2SovereignChain.sol | 36 +-- .../GlobalExitRootManagerL2SovereignChain.sol | 28 +-- docker/scripts/v2/deploy-dockerv2.sh | 17 +- package-lock.json | 224 ++++++++++-------- package.json | 4 +- .../upgradePessimistic/upgradePessimistic.ts | 8 +- 7 files changed, 183 insertions(+), 141 deletions(-) diff --git a/contracts/v2/PolygonZkEVMBridgeV2.sol b/contracts/v2/PolygonZkEVMBridgeV2.sol index cbd88c92d..1d4c5ef45 100644 --- a/contracts/v2/PolygonZkEVMBridgeV2.sol +++ b/contracts/v2/PolygonZkEVMBridgeV2.sol @@ -89,7 +89,8 @@ contract PolygonZkEVMBridgeV2 is bytes public gasTokenMetadata; // WETH address - // @note If WETH address is zero, means the gasToken of the network is ether, else means the network has a custom erc20 gas token. This value is set at initialization of the contract. In case gasTokenAddress != zero, a erc20 contract is deployed and the created address is set as WETH address, to handle wrapped ether + // @note WETH address will only be present when the native token is not ether, but another gasToken. + // This variable is set at the initialization of the contract in case there's a gas token differnet than ether, (gasTokenAddress != address(0) ) so a new wrapped Token will be deployed to handle ether that came from other networks TokenWrapped public WETHToken; /** @@ -619,7 +620,7 @@ contract PolygonZkEVMBridgeV2 is address destinationAddress, uint256 amount, bytes calldata metadata - ) external virtual ifNotEmergencyState { + ) external ifNotEmergencyState { // Destination network must be this networkID if (destinationNetwork != networkID) { revert DestinationNetworkInvalid(); @@ -932,7 +933,7 @@ contract PolygonZkEVMBridgeV2 is address destinationAddress, uint256 amount ) internal virtual { - // Burn tokens + // Mint tokens tokenWrapped.mint(destinationAddress, amount); } diff --git a/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol b/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol index 214c9b9c5..1b8ed0d3a 100644 --- a/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol +++ b/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol @@ -121,6 +121,10 @@ contract BridgeL2SovereignChain is // Set sovereign weth token or create new if not provided if (_sovereignWETHAddress == address(0)) { + // Health check for sovereign WETH address is mintable + if (_sovereignWETHAddressIsNotMintable == true) { + revert InvalidSovereignWETHAddressParams(); + } // Create a wrapped token for WETH, with salt == 0 WETHToken = _deployWrappedToken( 0, // salt @@ -163,18 +167,6 @@ contract BridgeL2SovereignChain is _; } - /** - * @notice Updated bridge manager address - * @param _bridgeManager Bridge manager address - */ - function setBridgeManager( - address _bridgeManager - ) external onlyBridgeManager { - if (_bridgeManager == address(0)) revert NotValidBridgeManager(); - bridgeManager = _bridgeManager; - emit SetBridgeManager(bridgeManager); - } - /** * @notice Remap multiple wrapped tokens to a new sovereign token address * @dev This function is a "multi/batch call" to `setSovereignTokenAddress` @@ -386,6 +378,18 @@ contract BridgeL2SovereignChain is ); } + /** + * @notice Updated bridge manager address + * @param _bridgeManager Bridge manager address + */ + function setBridgeManager( + address _bridgeManager + ) external onlyBridgeManager { + if (_bridgeManager == address(0)) revert NotValidBridgeManager(); + bridgeManager = _bridgeManager; + emit SetBridgeManager(bridgeManager); + } + /** * @notice Burn tokens from wrapped token to execute the bridge, if the token is not mintable it will be transferred * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain @@ -413,7 +417,7 @@ contract BridgeL2SovereignChain is /** * @notice Mints tokens from wrapped token to proceed with the claim, if the token is not mintable it will be transferred - * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + * note This function has been extracted to be able to override it by other contracts like BridgeL2SovereignChain * @param tokenWrapped Wrapped token to mint * @param destinationAddress Minted token receiver * @param amount Amount of tokens @@ -425,13 +429,13 @@ contract BridgeL2SovereignChain is ) internal override { // If is not mintable transfer instead of mint if (wrappedAddressIsNotMintable[address(tokenWrapped)]) { - // Transfer wETH + // Transfer tokens IERC20Upgradeable(address(tokenWrapped)).safeTransfer( destinationAddress, amount ); } else { - // Claim wETH + // Claim tokens tokenWrapped.mint(destinationAddress, amount); } } @@ -439,6 +443,7 @@ contract BridgeL2SovereignChain is // @note This function is not used in the current implementation. We overwrite it to improve deployed bytecode size function activateEmergencyState() external + pure override(IPolygonZkEVMBridgeV2, PolygonZkEVMBridgeV2) { revert NotValidBridgeManager(); @@ -446,6 +451,7 @@ contract BridgeL2SovereignChain is function deactivateEmergencyState() external + pure override(IPolygonZkEVMBridgeV2, PolygonZkEVMBridgeV2) { revert NotValidBridgeManager(); diff --git a/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol index d92e06258..ee835f3ad 100644 --- a/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol +++ b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol @@ -29,20 +29,6 @@ contract GlobalExitRootManagerL2SovereignChain is */ event RemoveLastGlobalExitRoot(bytes32 indexed removedGlobalExitRoot); - modifier onlyGlobalExitRootUpdater() { - // Only allowed to be called by GlobalExitRootUpdater or coinbase if GlobalExitRootUpdater is zero - if (globalExitRootUpdater == address(0)) { - if (block.coinbase != msg.sender) { - revert OnlyGlobalExitRootUpdater(); - } - } else { - if (globalExitRootUpdater != msg.sender) { - revert OnlyGlobalExitRootUpdater(); - } - } - _; - } - /** * @param _bridgeAddress PolygonZkEVMBridge contract address */ @@ -62,6 +48,20 @@ contract GlobalExitRootManagerL2SovereignChain is globalExitRootUpdater = _globalExitRootUpdater; } + modifier onlyGlobalExitRootUpdater() { + // Only allowed to be called by GlobalExitRootUpdater or coinbase if GlobalExitRootUpdater is zero + if (globalExitRootUpdater == address(0)) { + if (block.coinbase != msg.sender) { + revert OnlyGlobalExitRootUpdater(); + } + } else { + if (globalExitRootUpdater != msg.sender) { + revert OnlyGlobalExitRootUpdater(); + } + } + _; + } + /** * @notice Insert a new global exit root * @param _newRoot new global exit root to insert diff --git a/docker/scripts/v2/deploy-dockerv2.sh b/docker/scripts/v2/deploy-dockerv2.sh index 0b5b3c935..bd744334b 100755 --- a/docker/scripts/v2/deploy-dockerv2.sh +++ b/docker/scripts/v2/deploy-dockerv2.sh @@ -1,7 +1,8 @@ #!/bin/bash +# Set the -e option to stop the script if any command fails set -e -rm -rf docker/gethData/geth_data -DEV_PERIOD=1 docker compose -f docker/docker-compose.yml up -d geth +sudo rm -rf docker/gethData/geth_data +sudo DEV_PERIOD=1 docker compose -f docker/docker-compose.yml up -d geth sleep 5 node docker/scripts/fund-accounts.js cp docker/scripts/v2/deploy_parameters_docker.json deployment/v2/deploy_parameters.json @@ -9,10 +10,10 @@ cp docker/scripts/v2/create_rollup_parameters_docker.json deployment/v2/create_r npm run deploy:testnet:v2:localhost rm -rf docker/deploymentOutput mkdir docker/deploymentOutput -mv deployment/v2/deploy_output.json docker/deploymentOutput -mv deployment/v2/genesis.json docker/deploymentOutput -mv deployment/v2/create_rollup_output.json docker/deploymentOutput -DEV_PERIOD=1 docker compose -f docker/docker-compose.yml down -docker build -t hermeznetwork/geth-zkevm-contracts -f docker/Dockerfile . +sudo mv deployment/v2/deploy_output.json docker/deploymentOutput +sudo mv deployment/v2/genesis.json docker/deploymentOutput +sudo mv deployment/v2/create_rollup_output.json docker/deploymentOutput +sudo DEV_PERIOD=1 docker compose -f docker/docker-compose.yml down +sudo docker build -t hermeznetwork/geth-zkevm-contracts -f docker/Dockerfile . # Let it readable for the multiplatform build coming later! -chmod -R go+rxw docker/gethData \ No newline at end of file +sudo chmod -R go+rxw docker/gethData \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ec3103468..2b8a92363 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@openzeppelin/contracts": "4.8.2", "@openzeppelin/contracts-upgradeable": "4.8.2", - "@openzeppelin/contracts5": "npm:@openzeppelin/contracts@^5.0.0", + "@openzeppelin/contracts5": "npm:@openzeppelin/contracts@5.0.0", "@openzeppelin/hardhat-upgrades": "^2.5.1", "@types/yargs": "^17.0.28", "circomlibjs": "0.1.1", @@ -126,9 +126,9 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.664.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.664.0.tgz", - "integrity": "sha512-+GtXktvVgpreM2b+NJL9OqZGsOzHwlCUrO8jgQUvH/yA6Kd8QO2YFhQCp0C9sSzTteZJVqGBu8E0CQurxJHPbw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.679.0.tgz", + "integrity": "sha512-NwVq8YvInxQdJ47+zz4fH3BRRLC6lL+WLkvr242PVBbUOLRyK/lkwHlfiKUoeVIMyK5NF+up6TRg71t/8Bny6Q==", "dev": true, "dependencies": { "@smithy/types": "^3.5.0", @@ -139,9 +139,9 @@ } }, "node_modules/@aws-sdk/types/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@aws-sdk/util-utf8-browser": { @@ -154,9 +154,9 @@ } }, "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@cspotcode/source-map-support": { @@ -395,24 +395,27 @@ "dev": true }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -1981,81 +1984,81 @@ } }, "node_modules/@nomicfoundation/edr": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.6.3.tgz", - "integrity": "sha512-hThe5ORR75WFYTXKL0K2AyLDxkTMrG+VQ1yL9BhQYsuh3OIH+3yNDxMz2LjfvrpOrMmJ4kk5NKdFewpqDojjXQ==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.6.4.tgz", + "integrity": "sha512-YgrSuT3yo5ZQkbvBGqQ7hG+RDvz3YygSkddg4tb1Z0Y6pLXFzwrcEwWaJCFAVeeZxdxGfCgGMUYgRVneK+WXkw==", "dev": true, "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.6.3", - "@nomicfoundation/edr-darwin-x64": "0.6.3", - "@nomicfoundation/edr-linux-arm64-gnu": "0.6.3", - "@nomicfoundation/edr-linux-arm64-musl": "0.6.3", - "@nomicfoundation/edr-linux-x64-gnu": "0.6.3", - "@nomicfoundation/edr-linux-x64-musl": "0.6.3", - "@nomicfoundation/edr-win32-x64-msvc": "0.6.3" + "@nomicfoundation/edr-darwin-arm64": "0.6.4", + "@nomicfoundation/edr-darwin-x64": "0.6.4", + "@nomicfoundation/edr-linux-arm64-gnu": "0.6.4", + "@nomicfoundation/edr-linux-arm64-musl": "0.6.4", + "@nomicfoundation/edr-linux-x64-gnu": "0.6.4", + "@nomicfoundation/edr-linux-x64-musl": "0.6.4", + "@nomicfoundation/edr-win32-x64-msvc": "0.6.4" }, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.3.tgz", - "integrity": "sha512-hqtI7tYDqKG5PDmZ//Z65EH5cgH8VL/SAAu50rpHP7WAVfJWkOCcYbecywwF6nhHdonJbRTDGAeG1/+VOy6zew==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.4.tgz", + "integrity": "sha512-QNQErISLgssV9+qia8sIjRANqtbW8snSDvjspixT/kSQ5ZSGxxctTg7x72wPSrcu8+EBEveIe5uqENIp5GH8HQ==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.3.tgz", - "integrity": "sha512-4fGi79/lyOlRUORhCYsYb3sWqRHuHT7qqzyZfZuNOn8llaxmT1k36xNmvpyg37R8SzjnhT/DzoukSJrs23Ip9Q==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.4.tgz", + "integrity": "sha512-cjVmREiwByyc9+oGfvAh49IAw+oVJHF9WWYRD+Tm/ZlSpnEVWxrGNBak2bd/JSYjn+mZE7gmWS4SMRi4nKaLUg==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.3.tgz", - "integrity": "sha512-yFFTvGFMhfAvQ1Z2itUh1jpoUA+mVROyVELcaxjIq8fyg602lQmbS+NXkhQ+oaeDgJ+06mSENrHBg4fcfRf9cw==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.4.tgz", + "integrity": "sha512-96o9kRIVD6W5VkgKvUOGpWyUGInVQ5BRlME2Fa36YoNsRQMaKtmYJEU0ACosYES6ZTpYC8U5sjMulvPtVoEfOA==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.3.tgz", - "integrity": "sha512-pOKmd0Fa3a6BHg5qbjbl/jMRELVi9oazbfiuU7Bvgn/dpTK+ID3jwT0SXiuC2zxjmPByWgXL6G9XRf5BPAM2rQ==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.4.tgz", + "integrity": "sha512-+JVEW9e5plHrUfQlSgkEj/UONrIU6rADTEk+Yp9pbe+mzNkJdfJYhs5JYiLQRP4OjxH4QOrXI97bKU6FcEbt5Q==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.3.tgz", - "integrity": "sha512-3AUferhkLIXtLV63w5GjpHttzdxZ36i656XMy+pkBZbbiqnzIVeKWg6DJv1A94fQY16gB4gqj9CLq4CWvbNN6w==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.4.tgz", + "integrity": "sha512-nzYWW+fO3EZItOeP4CrdMgDXfaGBIBkKg0Y/7ySpUxLqzut40O4Mb0/+quqLAFkacUSWMlFp8nsmypJfOH5zoA==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.3.tgz", - "integrity": "sha512-fr6bD872WIBXe9YnTDi0CzYepMcYRgSnkVqn0yK4wRnIvKrloWhxXNVY45GVIl51aNZguBnvoA4WEt6HIazs3A==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.4.tgz", + "integrity": "sha512-QFRoE9qSQ2boRrVeQ1HdzU+XN7NUgwZ1SIy5DQt4d7jCP+5qTNsq8LBNcqhRBOATgO63nsweNUhxX/Suj5r1Sw==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.3.tgz", - "integrity": "sha512-sn34MvN1ajw2Oq1+Drpxej78Z0HfIzI4p4WlolupAV9dOZKzp2JAIQeLVfZpjIFbF3zuyxLPP4dUBrQoFPEqhA==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.4.tgz", + "integrity": "sha512-2yopjelNkkCvIjUgBGhrn153IBPLwnsDeNiq6oA0WkeM8tGmQi4td+PGi9jAriUDAkc59Yoi2q9hYA6efiY7Zw==", "dev": true, "engines": { "node": ">= 18" @@ -2489,9 +2492,9 @@ } }, "node_modules/@oclif/config/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@oclif/core": { @@ -2710,9 +2713,9 @@ } }, "node_modules/@oclif/core/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@oclif/errors": { @@ -2930,9 +2933,9 @@ } }, "node_modules/@oclif/help/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@oclif/help/node_modules/wrap-ansi": { @@ -3042,9 +3045,9 @@ } }, "node_modules/@oclif/parser/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@oclif/plugin-help": { @@ -3073,9 +3076,9 @@ }, "node_modules/@openzeppelin/contracts5": { "name": "@openzeppelin/contracts", - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.2.tgz", - "integrity": "sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.0.tgz", + "integrity": "sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw==", "dev": true }, "node_modules/@openzeppelin/defender-admin-client": { @@ -3813,9 +3816,9 @@ } }, "node_modules/@smithy/types": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.5.0.tgz", - "integrity": "sha512-QN0twHNfe8mNJdH9unwsCK13GURU7oEAZqkBI+rsvpv1jrmserO+WnLE7jidR9W/1dxwZ0u/CB01mV2Gms/K2Q==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.6.0.tgz", + "integrity": "sha512-8VXK/KzOHefoC65yRgCn5vG1cysPJjHnOVt9d0ybFQSmJgQj152vMn4EkYhGuaOmnnZvCPav/KnYyE6/KsNZ2w==", "dev": true, "dependencies": { "tslib": "^2.6.2" @@ -3825,9 +3828,9 @@ } }, "node_modules/@smithy/types/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@solidity-parser/parser": { @@ -4022,12 +4025,12 @@ "peer": true }, "node_modules/@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "version": "22.8.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.2.tgz", + "integrity": "sha512-NzaRNFV+FZkvK/KLCsNdTvID0SThyrs5SHB6tsD/lajr22FGC73N2QeDPM2wHtVde8mgcXuSsHQkH5cX1pbPLw==", "dev": true, "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/node-fetch": { @@ -4155,9 +4158,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -7038,6 +7041,16 @@ "node": ">=14.0.0" } }, + "node_modules/ethers/node_modules/@types/node": { + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "dev": true, + "peer": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, "node_modules/ethers/node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", @@ -7157,9 +7170,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", - "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", "dev": true, "peer": true }, @@ -16952,14 +16965,14 @@ } }, "node_modules/hardhat": { - "version": "2.22.13", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.13.tgz", - "integrity": "sha512-psVJX4FSXDpSXwsU8OcKTJN04pQEj9cFBMX5OPko+OFwbIoiOpvRmafa954/UaA1934npTj8sV3gaTSdx9bPbA==", + "version": "2.22.15", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.15.tgz", + "integrity": "sha512-BpTGa9PE/sKAaHi4s/S1e9WGv63DR1m7Lzfd60C8gSEchDPfAJssVRSq0MZ2v2k76ig9m0kHAwVLf5teYwu/Mw==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.6.3", + "@nomicfoundation/edr": "^0.6.4", "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-tx": "5.0.4", "@nomicfoundation/ethereumjs-util": "9.0.4", @@ -19864,9 +19877,9 @@ "dev": true }, "node_modules/pg": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.0.tgz", - "integrity": "sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==", + "version": "8.13.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", + "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==", "dev": true, "dependencies": { "pg-connection-string": "^2.7.0", @@ -20896,24 +20909,45 @@ "dev": true }, "node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", "dev": true, "hasInstallScript": true, "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/secp256k1/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/secp256k1/node_modules/elliptic": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, "node_modules/secp256k1/node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", "dev": true }, "node_modules/semaphore-async-await": { diff --git a/package.json b/package.json index 5976a2e91..5fb332e2c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@0xpolygonhermez/zkevm-contracts", - "description": "Core contracts for the Polygon Hermez zkEVM", + "description": "Core contracts for the Polygon Hermez zkEVM.", "version": "3.0.0", "repository": { "type": "git", @@ -34,7 +34,7 @@ "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@openzeppelin/contracts": "4.8.2", "@openzeppelin/contracts-upgradeable": "4.8.2", - "@openzeppelin/contracts5": "npm:@openzeppelin/contracts@^5.0.0", + "@openzeppelin/contracts5": "npm:@openzeppelin/contracts@5.0.0", "@openzeppelin/hardhat-upgrades": "^2.5.1", "@types/yargs": "^17.0.28", "circomlibjs": "0.1.1", diff --git a/upgrade/upgradePessimistic/upgradePessimistic.ts b/upgrade/upgradePessimistic/upgradePessimistic.ts index fe156df1b..68f3997c6 100644 --- a/upgrade/upgradePessimistic/upgradePessimistic.ts +++ b/upgrade/upgradePessimistic/upgradePessimistic.ts @@ -59,11 +59,11 @@ async function main() { } else { console.log("Multiplier gas used: ", upgradeParameters.multiplierGas); async function overrideFeeData() { - const feedata = await ethers.provider.getFeeData(); + const feeData = await ethers.provider.getFeeData(); return new ethers.FeeData( null, - ((feedata.maxFeePerGas as bigint) * BigInt(upgradeParameters.multiplierGas)) / 1000n, - ((feedata.maxPriorityFeePerGas as bigint) * BigInt(upgradeParameters.multiplierGas)) / 1000n + ((feeData.maxFeePerGas as bigint) * BigInt(upgradeParameters.multiplierGas)) / 1000n, + ((feeData.maxPriorityFeePerGas as bigint) * BigInt(upgradeParameters.multiplierGas)) / 1000n ); } currentProvider.getFeeData = overrideFeeData; @@ -99,7 +99,7 @@ async function main() { // prepare upgrades // Upgrade to rollup manager - const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager"); + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); const implRollupManager = await upgrades.prepareUpgrade(rollupManagerAddress, PolygonRollupManagerFactory, { constructorArgs: [globalExitRootManagerAddress, polAddress, bridgeAddress], From ddfd159beeb13b871d901b14c95e9b7ae972a3b1 Mon Sep 17 00:00:00 2001 From: Ignasi Date: Tue, 5 Nov 2024 11:07:54 +0100 Subject: [PATCH 8/8] Remove system address from final genesis state Update deploy scripts with more checks Improve upgrade presimistic script --- deployment/testnet/prepareTestnet.ts | 15 ++ deployment/v2/4_createRollup.ts | 31 ++- deployment/v2/utils/deployment-utils.ts | 8 +- deployment/v2/utils/updateVanillaGenesis.ts | 207 ++++++++++++++---- .../v2/create_rollup_parameters_docker.json | 2 +- .../upgradePessimistic/upgradePessimistic.ts | 45 +++- 6 files changed, 251 insertions(+), 57 deletions(-) diff --git a/deployment/testnet/prepareTestnet.ts b/deployment/testnet/prepareTestnet.ts index 5f208fb87..0a45e9d03 100644 --- a/deployment/testnet/prepareTestnet.ts +++ b/deployment/testnet/prepareTestnet.ts @@ -132,6 +132,21 @@ async function main() { } deployParameters.polTokenAddress = polTokenContract.target; + + /* + * Deployment gasToken address + * A erc20 is deployed in this testnet in case it's wanted to deploy a rollup that uses this token as the gas token + */ + const gasTokenName = "Gas Token"; + const gasTokenSymbol = "GAS"; + + const gasTokenFactory = await ethers.getContractFactory("ERC20", deployer); + const gasTokenContract = await gasTokenFactory.deploy(gasTokenName, gasTokenSymbol); + await gasTokenContract.waitForDeployment(); + deployParameters.gasTokenAddress = gasTokenContract.target; + console.log("#######################\n"); + console.log("gas token deployed to:", gasTokenContract.target); + fs.writeFileSync(pathDeployParameters, JSON.stringify(deployParameters, null, 1)); } diff --git a/deployment/v2/4_createRollup.ts b/deployment/v2/4_createRollup.ts index 80c76f350..48937bfd1 100644 --- a/deployment/v2/4_createRollup.ts +++ b/deployment/v2/4_createRollup.ts @@ -7,19 +7,19 @@ import fs = require("fs"); import * as dotenv from "dotenv"; dotenv.config({path: path.resolve(__dirname, "../../.env")}); import {ethers, upgrades} from "hardhat"; -import {HardhatEthersSigner} from "@nomicfoundation/hardhat-ethers/signers"; -const {create2Deployment} = require("../helpers/deployment-helpers"); const pathGenesis = path.join(__dirname, "./genesis.json"); +const pathGenesisSovereign = path.join(__dirname, "./genesis_sovereign.json"); import {processorUtils, Constants} from "@0xpolygonhermez/zkevm-commonjs"; const createRollupParameters = require("./create_rollup_parameters.json"); -let genesis = require("./genesis.json"); +let genesis = require(pathGenesis); const deployOutput = require("./deploy_output.json"); import "../helpers/utils"; import updateVanillaGenesis from "./utils/updateVanillaGenesis"; const pathOutputJson = path.join(__dirname, "./create_rollup_output.json"); +const deployParameters = require("./deploy_parameters.json"); import { PolygonRollupManager, @@ -263,12 +263,19 @@ async function main() { ) as PolygonZkEVMBridgeV2; if ( createRollupParameters.gasTokenAddress && - createRollupParameters.gasTokenAddress != "" && - createRollupParameters.gasTokenAddress != ethers.ZeroAddress + createRollupParameters.gasTokenAddress !== "" && + createRollupParameters.gasTokenAddress !== ethers.ZeroAddress ) { + // If gas token address is "deployed" use the one from deploy parameters, erc20 deployed at prepare testnet script + if(createRollupParameters.gasTokenAddress == "deployed") { + createRollupParameters.gasTokenAddress = deployParameters.gasTokenAddress; + } // Get token metadata gasTokenMetadata = await polygonZkEVMBridgeContract.getTokenMetadata(createRollupParameters.gasTokenAddress); - + // If gas token metadata includes `0x124e4f545f56414c49445f454e434f44494e47 (NOT_VALID_ENCODING)` means there is no erc20 token deployed at the selected gas token network + if(gasTokenMetadata.includes("124e4f545f56414c49445f454e434f44494e47")) { + throw new Error(`Invalid gas token address, no ERC20 token deployed at the selected gas token network ${createRollupParameters.gasTokenAddress}`); + } const wrappedData = await polygonZkEVMBridgeContract.wrappedTokenToTokenInfo( createRollupParameters.gasTokenAddress ); @@ -375,7 +382,6 @@ async function main() { rollupID: rollupID, gasTokenAddress, gasTokenNetwork, - globalExitRootManager: Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2, polygonRollupManager: ethers.ZeroAddress, gasTokenMetadata, bridgeManager: sovereignParams.bridgeManager, @@ -384,6 +390,15 @@ async function main() { globalExitRootUpdater: sovereignParams.globalExitRootUpdater, }; genesis = await updateVanillaGenesis(genesis, chainID, initializeParams); + // Add weth address to deployment output if gas token address is provided and sovereignWETHAddress is not provided + if ( gasTokenAddress !== ethers.ZeroAddress && + ethers.isAddress(gasTokenAddress) && + (sovereignParams.sovereignWETHAddress === ethers.ZeroAddress || !ethers.isAddress(sovereignParams.sovereignWETHAddress))) { + const wethObject = genesis.genesis.find(function (obj) { + return obj.contractName == "WETH"; + }); + outputJson.WETHAddress = wethObject.address; + } } else { if (consensusContract === "PolygonPessimisticConsensus") { // Add the first batch of the created rollup @@ -463,7 +478,7 @@ async function main() { // Rewrite updated genesis in case of vanilla client if (isVanillaClient) { - fs.writeFileSync(pathGenesis, JSON.stringify(genesis, null, 1)); + fs.writeFileSync(pathGenesisSovereign, JSON.stringify(genesis, null, 1)); } fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); } diff --git a/deployment/v2/utils/deployment-utils.ts b/deployment/v2/utils/deployment-utils.ts index 63c473ba8..30bc04ce2 100644 --- a/deployment/v2/utils/deployment-utils.ts +++ b/deployment/v2/utils/deployment-utils.ts @@ -2,7 +2,11 @@ const padTo32Bytes = (value) => { const hexValue = value.startsWith("0x") ? value.slice(2) : value; // Remove '0x' return "0x" + hexValue.padStart(64, "0"); // Pad to 64 hex digits }; - +const padTo20Bytes = (value) => { + const hexValue = value.startsWith("0x") ? value.slice(2) : value; // Remove '0x' + return "0x" + hexValue.padStart(40, "0"); // Pad to 40 hex digits +}; export { - padTo32Bytes + padTo32Bytes, + padTo20Bytes } \ No newline at end of file diff --git a/deployment/v2/utils/updateVanillaGenesis.ts b/deployment/v2/utils/updateVanillaGenesis.ts index cd41d3c58..681c87957 100644 --- a/deployment/v2/utils/updateVanillaGenesis.ts +++ b/deployment/v2/utils/updateVanillaGenesis.ts @@ -3,7 +3,8 @@ import {ethers} from "hardhat"; const {getContractAddress} = require("@ethersproject/address"); const bridgeContractName = "BridgeL2SovereignChain"; import {expect} from "chai"; -import {padTo32Bytes} from "./deployment-utils"; +import {padTo32Bytes, padTo20Bytes} from "./deployment-utils"; + async function updateVanillaGenesis(genesis, chainID, initializeParams) { // Load genesis on a zkEVMDB const poseidon = await getPoseidon(); @@ -31,8 +32,8 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { type: 11, deltaTimestamp: 3, l1Info: { - globalExitRoot: "0x090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9", - blockHash: "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + globalExitRoot: ethers.ZeroAddress, // Can be any value + blockHash: "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", // Can be any value timestamp: "42", }, indexL1InfoTree: 0, @@ -72,7 +73,11 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { const oldBridge = genesis.genesis.find(function (obj) { return obj.contractName == "PolygonZkEVMBridgeV2"; }); - const deployGERData = await gerFactory.getDeployTransaction(oldBridge.address); + // Get bridge proxy address + const bridgeProxy = genesis.genesis.find(function (obj) { + return obj.contractName == "PolygonZkEVMBridgeV2 proxy"; + }); + const deployGERData = await gerFactory.getDeployTransaction(bridgeProxy.address); injectedTx.data = deployGERData.data; txObject = ethers.Transaction.from(injectedTx); const txDeployGER = processorUtils.rawTxToCustomRawTx(txObject.serialized); @@ -112,12 +117,14 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { ); // Add changeL2Block tx batch2.addRawTx(`0x${rawChangeL2BlockTx}`); + const gerProxy = genesis.genesis.find(function (obj) { + return obj.contractName == "PolygonZkEVMGlobalExitRootL2 proxy"; + }); // Initialize bridge const { rollupID, gasTokenAddress, gasTokenNetwork, - globalExitRootManager, polygonRollupManager, gasTokenMetadata, bridgeManager, @@ -131,7 +138,7 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { rollupID, gasTokenAddress, gasTokenNetwork, - globalExitRootManager, + gerProxy.address, // Global exit root manager address from base genesis polygonRollupManager, gasTokenMetadata, bridgeManager, @@ -139,10 +146,6 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { sovereignWETHAddressIsNotMintable, ] ); - // Get bridge proxy address - const bridgeProxy = genesis.genesis.find(function (obj) { - return obj.contractName == "PolygonZkEVMBridgeV2 proxy"; - }); injectedTx.to = bridgeProxy.address; injectedTx.data = initializeData; txObject = ethers.Transaction.from(injectedTx); @@ -152,9 +155,6 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { batch2.addRawTx(txInitializeBridge); // Initialize GER Manager - const gerProxy = genesis.genesis.find(function (obj) { - return obj.contractName == "PolygonZkEVMGlobalExitRootL2 proxy"; - }); const initializeGERData = gerFactory.interface.encodeFunctionData("initialize", [globalExitRootUpdater]); // Update injectedTx to initialize GER injectedTx.to = gerProxy.address; @@ -174,8 +174,15 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { bridgeProxy.contractName = bridgeContractName + " proxy"; bridgeProxy.storage = await zkEVMDB2.dumpStorage(bridgeProxy.address); // If bridge initialized with a zero sovereign weth address and a non zero gas token, we should add created erc20 weth contract to the genesis - if (gasTokenAddress !== ethers.ZeroAddress && sovereignWETHAddress === ethers.ZeroAddress) { - const wethAddress = bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"]; + let wethAddress; + if ( + gasTokenAddress !== ethers.ZeroAddress && + ethers.isAddress(gasTokenAddress) && + (sovereignWETHAddress === ethers.ZeroAddress || !ethers.isAddress(sovereignWETHAddress)) + ) { + wethAddress = padTo20Bytes( + bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"] + ); const wethGenesis = { contractName: "WETH", balance: "0", @@ -197,42 +204,130 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { return acc; }, {}); - // Sanity check bridge storage - if (rollupID !== 0) { - // RollupID value is stored at position 68 with globalExitRootManager address. Slice from byte 2 to 2-8 to get the rollupID - expect( - bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"].slice( - 2 + 54, - 2 + 54 + 8 - ) - ).to.include(rollupID.toString(16)); - } - if (gasTokenAddress !== ethers.ZeroAddress) { + // CHECK BRIDGE PROXY STORAGE + // Storage value pointing bridge implementation + expect(bridgeProxy.storage["0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"]).to.include( + oldBridge.address.toLowerCase().slice(2) + ); + + // Storage value of proxyAdmin + const proxyAdminObject = genesis.genesis.find(function (obj) { + return obj.contractName == "ProxyAdmin"; + }); + expect(bridgeProxy.storage["0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"]).to.include( + proxyAdminObject.address.toLowerCase().slice(2) + ); + + // Storage value of bridge manager + expect(bridgeProxy.storage["0x00000000000000000000000000000000000000000000000000000000000000a3"]).to.include( + bridgeManager.toLowerCase().slice(2) + ); + + // Storage value for the _initialized uint8 variable of Initializable.sol contract, incremented each time the contract is successfully initialized. It also stores the _initializing param set to true when an initialization function is being executed, and it reverts to false once the initialization completed. + expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000000"]).to.equal( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ); + + // Storage value for the _status variable of ReentrancyGuardUpgradeable contract. Tracks the current "status" of the contract to enforce the non-reentrant behavior. Default value is 1 (_NOT_ENTERED) + expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000001"]).to.equal( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ); + + // Storage value for global exit root manager (proxy) address + expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"]).to.include( + gerProxy.address.toLowerCase().slice(2) + ); + + // Storage value for rollup/network id + // RollupID value is stored at position 68 with globalExitRootManager address. Slice from byte 2 to 2-8 to get the rollupID + expect( + bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"].slice( + 2 + 54, + 2 + 54 + 8 + ) + ).to.include(rollupID.toString(16)); + + // Storage value for gas token address + if (gasTokenAddress !== ethers.ZeroAddress && ethers.isAddress(gasTokenAddress)) { expect( ethers.toBigInt(bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006d"]) ).to.equal( ethers.toBigInt(`${ethers.toBeHex(gasTokenNetwork)}${gasTokenAddress.replace(/^0x/, "")}`.toLowerCase()) ); - } - if (sovereignWETHAddress !== ethers.ZeroAddress) { - expect(bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"]).to.include( - sovereignWETHAddress.toLowerCase().slice(2) + if (ethers.isAddress(sovereignWETHAddress) && sovereignWETHAddress !== ethers.ZeroAddress) { + // Storage value for sovereignWETH address (ony if network with native gas token) and sovereignWethAddress is set + expect( + bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"] + ).to.include(sovereignWETHAddress.toLowerCase().slice(2)); + + // Storage address for sovereignWETHAddressIsNotMintable mapping + // To get the key we encode the key of the mapping with the position in the mapping + if (sovereignWETHAddressIsNotMintable) { + const mappingSlot = 162; // Slot of the mapping in the bridge contract + const key = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["address", "uint256"], + [sovereignWETHAddress, mappingSlot] + ) + ); + expect(bridgeProxy.storage[key]).to.equal( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ); + } + } else { + // Storage value for WETH address (ony if network with native gas token), deployed at bridge initialization + expect( + bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"] + ).to.include(wethAddress.toLowerCase().slice(2)); + + // CHECK WETH STORAGE + const wethOject = genesis.genesis.find(function (obj) { + return obj.contractName == "WETH"; + }); + + // Storage for erc20 name 'Wrapped Ether' + expect(wethOject.storage["0x0000000000000000000000000000000000000000000000000000000000000003"]).to.equal( + "0x577261707065642045746865720000000000000000000000000000000000001a" + ); + + // Storage for erc20 code 'WETH' + expect(wethOject.storage["0x0000000000000000000000000000000000000000000000000000000000000004"]).to.equal( + "0x5745544800000000000000000000000000000000000000000000000000000008" + ); + } + + // Storage values for gasTokenMetadata, its a bytes variable + let offset = 2 + 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142a"]).to.include( + gasTokenMetadata.slice(2, offset) ); - } - if (sovereignWETHAddressIsNotMintable) { - expect(bridgeProxy.storage["0xc7edf51165adec508a5250d96d0588939529f9442a12e2ffa25d7692caac0ef0"]).to.equal( - "0x0000000000000000000000000000000000000000000000000000000000000001" + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142b"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142c"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142d"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142e"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142f"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db71430"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) ); } - expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"]).to.include( - globalExitRootManager.toLowerCase().slice(2) - ); - expect(bridgeProxy.storage["0x00000000000000000000000000000000000000000000000000000000000000a3"]).to.include( - bridgeManager.toLowerCase().slice(2) - ); - // Check bridgeAddress is included in ger bytecode - expect(oldGer.bytecode).to.include(oldBridge.address.toLowerCase().slice(2)); + // Check bridge proxy Address is included in ger bytecode + expect(oldGer.bytecode).to.include(bridgeProxy.address.toLowerCase().slice(2)); // Update bridgeProxy storage gerProxy.contractName = gerContractName + " proxy"; @@ -242,12 +337,36 @@ async function updateVanillaGenesis(genesis, chainID, initializeParams) { return acc; }, {}); - // Sanity check ger storage + // CHECK GER PROXY STORAGE + // Storage value of proxy implementation + expect(gerProxy.storage["0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"]).to.include( + oldGer.address.toLowerCase().slice(2) + ); + + // Storage value of proxyAdmin + expect(gerProxy.storage["0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"]).to.include( + proxyAdminObject.address.toLowerCase().slice(2) + ); + + // Storage value of global exit root updater expect(gerProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000034"]).to.include( globalExitRootUpdater.toLowerCase().slice(2) ); + + // Create a new zkEVM to generate a genesis an empty system address storage + const zkEVMDB3 = await ZkEVMDB.newZkEVM( + new MemDB(F), + poseidon, + genesisRoot, + accHashInput, + genesis.genesis, + null, + null, + chainID + ); // update genesis root - genesis.root = smtUtils.h4toString(zkEVMDB2.getCurrentStateRoot()); + genesis.root = smtUtils.h4toString(zkEVMDB3.getCurrentStateRoot()); + return genesis; } diff --git a/docker/scripts/v2/create_rollup_parameters_docker.json b/docker/scripts/v2/create_rollup_parameters_docker.json index e3de619a0..7e99c5a88 100644 --- a/docker/scripts/v2/create_rollup_parameters_docker.json +++ b/docker/scripts/v2/create_rollup_parameters_docker.json @@ -8,7 +8,7 @@ "adminZkEVM": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "forkID": 11, "consensusContract": "PolygonPessimisticConsensus", - "gasTokenAddress": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "gasTokenAddress": "deployed", "deployerPvtKey": "", "maxFeePerGas": "", "maxPriorityFeePerGas": "", diff --git a/upgrade/upgradePessimistic/upgradePessimistic.ts b/upgrade/upgradePessimistic/upgradePessimistic.ts index 68f3997c6..c9bf51f15 100644 --- a/upgrade/upgradePessimistic/upgradePessimistic.ts +++ b/upgrade/upgradePessimistic/upgradePessimistic.ts @@ -3,6 +3,7 @@ import {expect} from "chai"; import path = require("path"); import fs = require("fs"); +import {utils} from "ffjavascript"; import * as dotenv from "dotenv"; dotenv.config({path: path.resolve(__dirname, "../../.env")}); @@ -125,7 +126,11 @@ async function main() { const operationRollupManager = genOperation( proxyAdmin.target, 0, // value - proxyAdmin.interface.encodeFunctionData("upgrade", [rollupManagerAddress, implRollupManager]), // data + proxyAdmin.interface.encodeFunctionData("upgradeAndCall", [ + rollupManagerAddress, + implRollupManager, + PolygonRollupManagerFactory.interface.encodeFunctionData("initialize", []), + ]), // data ethers.ZeroHash, // predecessor salt // salt ); @@ -157,7 +162,43 @@ async function main() { executeData, timelockContractAddress: timelockAddress, }; - fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); + + // Decode the scheduleData for better readability + const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); + const paramsArray = timelockTx?.fragment.inputs; + const objectDecoded = {}; + + for (let i = 0; i < paramsArray?.length; i++) { + const currentParam = paramsArray[i]; + objectDecoded[currentParam.name] = timelockTx?.args[i]; + + if (currentParam.name == "payloads") { + // for each payload + const payloads = timelockTx?.args[i]; + for (let j = 0; j < payloads.length; j++) { + const data = payloads[j]; + const decodedProxyAdmin = proxyAdmin.interface.parseTransaction({ + data, + }); + + const resultDecodeProxyAdmin = {}; + resultDecodeProxyAdmin.signature = decodedProxyAdmin?.signature; + resultDecodeProxyAdmin.selector = decodedProxyAdmin?.selector; + + const paramsArrayData = decodedProxyAdmin?.fragment.inputs; + + for (let n = 0; n < paramsArrayData?.length; n++) { + const currentParam = paramsArrayData[n]; + resultDecodeProxyAdmin[currentParam.name] = decodedProxyAdmin?.args[n]; + } + objectDecoded[`decodePayload_${j}`] = resultDecodeProxyAdmin; + } + } + } + + outputJson.decodedScheduleData = objectDecoded; + + fs.writeFileSync(pathOutputJson, JSON.stringify(utils.stringifyBigInts(outputJson), null, 1)); } main().catch((e) => {