From e251bbe96b2e9390a0a07088fc01eb780deb3e6a Mon Sep 17 00:00:00 2001 From: Zou Guangxian Date: Thu, 14 Dec 2023 22:59:57 +0800 Subject: [PATCH] chore: update the license information --- LICENSE-BUSL.1.1 | 94 ++++++++++ LICENSE-MIT | 25 +++ .../uln/dvn/adapters/CCIP/CCIPDVNAdapter.sol | 152 +++++++++++++++ .../adapters/CCIP/CCIPDVNAdapterFeeLib.sol | 7 + .../uln/dvn/adapters/DVNAdapterBase.sol | 162 ++++++++++++++++ .../uln/dvn/adapters/DVNAdapterFeeLibBase.sol | 20 ++ .../dvn/adapters/axelar/AxelarDVNAdapter.sol | 156 +++++++++++++++ .../axelar/AxelarDVNAdapterFeeLib.sol | 7 + .../uln/interfaces/IDVNAdapterFeeLib.sol | 13 ++ .../uln/uln301/mocks/NonceContractMock.sol | 2 +- messagelib/foundry.toml | 3 + messagelib/package.json | 2 + messagelib/test/DVNAdapterBase.t.sol | 177 ++++++++++++++++++ messagelib/test/DVNAdapterFeeLibBase.t.sol | 35 ++++ messagelib/test/mocks/ReceiveLibMock.sol | 51 +++++ messagelib/test/mocks/SendLibMock.sol | 76 ++++++++ oapp/contracts/oapp/OApp.sol | 1 + oapp/contracts/oapp/OAppCore.sol | 1 + oapp/contracts/oapp/OAppReceiver.sol | 1 + oapp/contracts/oapp/OAppSender.sol | 1 + oapp/contracts/oapp/examples/ExampleOApp.sol | 1 + .../examples/ExampleOAppPreCrimeSimulator.sol | 1 + .../oapp/examples/ExampleOAppReceiver.sol | 1 + .../oapp/examples/ExampleOAppSender.sol | 1 + oapp/contracts/oapp/examples/OmniCounter.sol | 2 +- .../oapp/examples/OmniCounterPreCrime.sol | 2 +- .../oapp/interfaces/IOAppComposer.sol | 1 + oapp/contracts/oapp/interfaces/IOAppCore.sol | 1 + .../oapp/interfaces/IOAppMsgInspector.sol | 1 + .../oapp/interfaces/IOAppOptionsType3.sol | 1 + oapp/contracts/oapp/libs/OAppOptionsType3.sol | 1 + oapp/contracts/oapp/libs/OptionsBuilder.sol | 2 +- oapp/contracts/oft/OFT.sol | 1 + oapp/contracts/oft/OFTAdapter.sol | 1 + oapp/contracts/oft/OFTCore.sol | 1 + oapp/contracts/oft/OFTPrecrime.sol | 3 +- oapp/contracts/oft/extensions/Fee.sol | 1 + oapp/contracts/oft/interfaces/IOFT.sol | 1 + .../contracts/oft/libs/OFTComposeMsgCodec.sol | 1 + oapp/contracts/oft/libs/OFTMsgCodec.sol | 1 + .../precrime/OAppPreCrimeSimulator.sol | 1 + oapp/contracts/precrime/PreCrime.sol | 2 +- .../interfaces/IOAppPreCrimeSimulator.sol | 1 + .../precrime/interfaces/IPreCrime.sol | 1 + oapp/contracts/precrime/libs/Packet.sol | 2 +- oapp/foundry.toml | 1 + package.json | 6 + .../contracts/messagelib/libs/BitMaps.sol | 2 +- protocol/foundry.toml | 1 + yarn.lock | 162 +++++++++++++++- 50 files changed, 1181 insertions(+), 9 deletions(-) create mode 100644 LICENSE-BUSL.1.1 create mode 100644 LICENSE-MIT create mode 100644 messagelib/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapter.sol create mode 100644 messagelib/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapterFeeLib.sol create mode 100644 messagelib/contracts/uln/dvn/adapters/DVNAdapterBase.sol create mode 100644 messagelib/contracts/uln/dvn/adapters/DVNAdapterFeeLibBase.sol create mode 100644 messagelib/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapter.sol create mode 100644 messagelib/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapterFeeLib.sol create mode 100644 messagelib/contracts/uln/interfaces/IDVNAdapterFeeLib.sol create mode 100644 messagelib/test/DVNAdapterBase.t.sol create mode 100644 messagelib/test/DVNAdapterFeeLibBase.t.sol create mode 100644 messagelib/test/mocks/ReceiveLibMock.sol create mode 100644 messagelib/test/mocks/SendLibMock.sol diff --git a/LICENSE-BUSL.1.1 b/LICENSE-BUSL.1.1 new file mode 100644 index 0000000..2b28c2a --- /dev/null +++ b/LICENSE-BUSL.1.1 @@ -0,0 +1,94 @@ +Business Source License 1.1 + +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. + +----------------------------------------------------------------------------- + +Parameters + +Licensor: LayerZero Labs Ltd + +Licensed Work: LayerZero Protocol + The Licensed Work is (c) 2023 LayerZero Labs Ltd + +Change Date: 2026-12-01 + +----------------------------------------------------------------------------- + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative +works, redistribute, and make non-production use of the Licensed Work. The +Licensor may make an Additional Use Grant, above, permitting limited +production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly +available distribution of a specific version of the Licensed Work under this +License, whichever comes first, the Licensor hereby grants you rights under +the terms of the Change License, and the rights granted in the paragraph +above terminate. + +If your use of the Licensed Work does not comply with the requirements +currently in effect as described in this License, you must purchase a +commercial license from the Licensor, its affiliated entities, or authorized +resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works +of the Licensed Work, are subject to this License. This License applies +separately for each version of the Licensed Work and the Change Date may vary +for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy +of the Licensed Work. If you receive the Licensed Work in original or +modified form from a third party, the terms and conditions set forth in this +License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically +terminate your rights under this License for the current and all other +versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of +Licensor or its affiliates (provided that you may use a trademark or logo of +Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +TITLE. + +MariaDB hereby grants you permission to use this License’s text to license +your works, and to refer to it using the trademark "Business Source License", +as long as you comply with the Covenants of Licensor below. + +----------------------------------------------------------------------------- + +Covenants of Licensor + +In consideration of the right to use this License’s text and the "Business +Source License" name and trademark, Licensor covenants to MariaDB, and to all +other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, + or a license that is compatible with GPL Version 2.0 or a later version, + where "compatible" means that software provided under the Change License can + be included in a program with software provided under GPL Version 2.0 or a + later version. Licensor may specify additional Change Licenses without + limitation. + +2. To either: (a) specify an additional grant of rights to use that does not + impose any additional restriction on the right granted in this License, as + the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. + +----------------------------------------------------------------------------- + +Notice + +The Business Source License (this document, or the "License") is not an Open +Source license. However, the Licensed Work will eventually be made available +under an Open Source License, as stated in this License. \ No newline at end of file diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..0029fa9 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2018 + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/messagelib/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapter.sol b/messagelib/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapter.sol new file mode 100644 index 0000000..572f05c --- /dev/null +++ b/messagelib/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapter.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity 0.8.22; + +import { IRouterClient } from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol"; +import { CCIPReceiver } from "@chainlink/contracts-ccip/src/v0.8/ccip/applications/CCIPReceiver.sol"; +import { Client } from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; + +import { DVNAdapterBase } from "../DVNAdapterBase.sol"; + +contract CCIPDVNAdapter is CCIPReceiver, DVNAdapterBase { + struct DstConfigParam { + uint32 dstEid; + // https://docs.chain.link/ccip/supported-networks/v1_2_0/testnet#ethereum-sepolia + // https://docs.chain.link/ccip/supported-networks/v1_0_0/mainnet + uint64 chainSelector; + uint16 multiplierBps; + uint256 gasLimit; + bytes peer; + } + + struct DstConfig { + uint64 chainSelector; + uint16 multiplierBps; + uint256 gasLimit; + bytes peer; + } + + address private constant NATIVE_GAS_TOKEN_ADDRESS = address(0); + + event DstConfigSet(DstConfigParam[] params); + + mapping(uint32 dstEid => DstConfig config) public dstConfig; + mapping(uint64 chainSelector => uint32 eid) public CCIPChainToEid; + + constructor( + address _sendLib, + address _receiveLib, + address[] memory _admins, + address router + ) CCIPReceiver(router) DVNAdapterBase(_sendLib, _receiveLib, _admins) {} + + /// @notice sets configuration (`chainSelector`, `multiplierBps`, `gasLimit` and `peer`) for destination chains + /// @dev The `multiplierBps` can be updated separately using `setDstMultiplierBps` function + /// @param _params array of chain configurations + function setDstConfig(DstConfigParam[] calldata _params) external onlyAdmin { + for (uint256 i = 0; i < _params.length; i++) { + DstConfigParam calldata param = _params[i]; + + delete CCIPChainToEid[dstConfig[param.dstEid].chainSelector]; + + CCIPChainToEid[param.chainSelector] = param.dstEid; + dstConfig[param.dstEid] = DstConfig({ + chainSelector: param.chainSelector, + multiplierBps: param.multiplierBps, + gasLimit: param.gasLimit, + peer: param.peer + }); + } + + emit DstConfigSet(_params); + } + + /// @notice sets fee multiplier in basis points for destination chains + /// @param _params array of multipliers for destination chains + function setDstMultiplier(DstMultiplierParam[] calldata _params) external onlyAdmin { + for (uint256 i = 0; i < _params.length; i++) { + DstMultiplierParam calldata param = _params[i]; + dstConfig[param.dstEid].multiplierBps = param.multiplierBps; + } + + emit DstMultiplierSet(_params); + } + + function getFee( + uint32 _dstEid, + uint64 /*_confirmations*/, + address _sender, + bytes calldata /*_options*/ + ) external view override returns (uint256 fee) { + DstConfig storage config = dstConfig[_dstEid]; + + Client.EVM2AnyMessage memory message = _createCCIPMessage( + new bytes(PACKET_HEADER_SIZE), + bytes32(0), + config.peer, + config.gasLimit + ); + + fee = _getCCIPFee(config.chainSelector, message); + if (address(feeLib) != address(0)) { + fee = feeLib.getFee(_dstEid, _sender, defaultMultiplierBps, config.multiplierBps, fee); + } + } + + function assignJob( + AssignJobParam calldata _param, + bytes calldata /*_options*/ + ) external payable override onlySendLib returns (uint256 fee) { + DstConfig memory config = dstConfig[_param.dstEid]; + + Client.EVM2AnyMessage memory message = _createCCIPMessage( + _param.packetHeader, + _param.payloadHash, + config.peer, + config.gasLimit + ); + + fee = _getCCIPFee(config.chainSelector, message); + _assertBalanceAndWithdrawFee(fee); + + IRouterClient(getRouter()).ccipSend{ value: fee }(config.chainSelector, message); + + if (address(feeLib) != address(0)) { + fee = feeLib.getFee(_param.dstEid, _param.sender, defaultMultiplierBps, config.multiplierBps, fee); + } + } + + function _createCCIPMessage( + bytes memory _packetHeader, + bytes32 _payloadHash, + bytes memory _receiver, + uint256 _gasLimit + ) private pure returns (Client.EVM2AnyMessage memory message) { + message = Client.EVM2AnyMessage({ + receiver: _receiver, + data: _encodePayload(_packetHeader, _payloadHash), + tokenAmounts: new Client.EVMTokenAmount[](0), // Empty array indicating no tokens are being sent + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({ gasLimit: _gasLimit, strict: false })), + feeToken: NATIVE_GAS_TOKEN_ADDRESS + }); + } + + function _getCCIPFee( + uint64 _dstChainSelector, + Client.EVM2AnyMessage memory _message + ) private view returns (uint256 ccipFee) { + ccipFee = IRouterClient(getRouter()).getFee(_dstChainSelector, _message); + } + + function _ccipReceive(Client.Any2EVMMessage memory _message) internal override { + _assertPeer(_message.sourceChainSelector, _message.sender); + _verify(_message.data); + } + + function _assertPeer(uint64 _sourceChainSelector, bytes memory _sourceAddress) private view { + uint32 sourceEid = CCIPChainToEid[_sourceChainSelector]; + bytes memory sourcePeer = dstConfig[sourceEid].peer; + + if (keccak256(_sourceAddress) != keccak256(sourcePeer)) revert Unauthorized(); + } +} diff --git a/messagelib/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapterFeeLib.sol b/messagelib/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapterFeeLib.sol new file mode 100644 index 0000000..e39207e --- /dev/null +++ b/messagelib/contracts/uln/dvn/adapters/CCIP/CCIPDVNAdapterFeeLib.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity 0.8.22; + +import { DVNAdapterFeeLibBase } from "../DVNAdapterFeeLibBase.sol"; + +contract CCIPDVNAdapterFeeLib is DVNAdapterFeeLibBase {} diff --git a/messagelib/contracts/uln/dvn/adapters/DVNAdapterBase.sol b/messagelib/contracts/uln/dvn/adapters/DVNAdapterBase.sol new file mode 100644 index 0000000..9be901f --- /dev/null +++ b/messagelib/contracts/uln/dvn/adapters/DVNAdapterBase.sol @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity 0.8.22; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { BytesLib } from "solidity-bytes-utils/contracts/BytesLib.sol"; + +import { Transfer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/Transfer.sol"; +import { IMessageLib } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol"; +import { ISendLib } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol"; + +import { ILayerZeroDVN } from "../../interfaces/ILayerZeroDVN.sol"; +import { IReceiveUlnE2 } from "../../interfaces/IReceiveUlnE2.sol"; +import { IDVNAdapterFeeLib } from "../../interfaces/IDVNAdapterFeeLib.sol"; + +/// @title DVNAdapterBase +/// @notice base contract for DVN adapters +/// @dev limitations: +/// - doesn't accept alt token +/// - doesn't respect block confirmations +/// - doesn't support multiple libraries. One deployment per library +abstract contract DVNAdapterBase is Ownable, ILayerZeroDVN { + using BytesLib for bytes; + + struct DstMultiplierParam { + uint32 dstEid; + uint16 multiplierBps; + } + + /// @dev for protocols that doesn't allow to configure outbound block confirmations per message, + /// ignore confirmations set in the config and use the maximum possible confirmations to prevent failure + /// in the receive library due to insufficient confirmations if the config was changed before the message is received + uint64 internal constant MAX_CONFIRMATIONS = type(uint64).max; + + uint256 internal constant PACKET_HEADER_SIZE = 81; + uint256 internal constant PAYLOAD_HASH_SIZE = 32; + uint256 internal constant PAYLOAD_SIZE = PACKET_HEADER_SIZE + PAYLOAD_HASH_SIZE; + + ISendLib public immutable sendLib; + IReceiveUlnE2 public immutable receiveLib; + IDVNAdapterFeeLib public feeLib; + + uint16 public defaultMultiplierBps = 10_000; // no multiplier + mapping(address admin => bool) public admins; + + error OnlySendLib(); + error Unauthorized(); + error InvalidPayloadSize(); + error VersionMismatch(); + + event AdminSet(address indexed admin, bool isAdmin); + event DefaultMultiplierSet(uint16 multiplierBps); + event DstMultiplierSet(DstMultiplierParam[] params); + event FeeLibSet(address indexed feeLib); + event FeeWithdrawn(address indexed to, uint256 amount); + event TokenWithdrawn(address indexed to, address token, uint256 amount); + + modifier onlySendLib() { + if (msg.sender != address(sendLib)) revert OnlySendLib(); + _; + } + + modifier onlyAdmin() { + if (!admins[msg.sender]) revert Unauthorized(); + _; + } + + constructor(address _sendLib, address _receiveLib, address[] memory _admins) { + (uint64 sendMajor, uint8 sendMinor, uint8 sendEndpoint) = IMessageLib(_sendLib).version(); + (uint64 receiveMajor, uint8 receiveMinor, uint8 receiveEndpoint) = IMessageLib(_receiveLib).version(); + + if (sendMajor != receiveMajor || sendMinor != receiveMinor || sendEndpoint != receiveEndpoint) { + revert VersionMismatch(); + } + + sendLib = ISendLib(_sendLib); + receiveLib = IReceiveUlnE2(_receiveLib); + + for (uint256 i = 0; i < _admins.length; i++) { + admins[_admins[i]] = true; + emit AdminSet(_admins[i], true); + } + } + + function setAdmin(address _admin, bool _isAdmin) external onlyOwner { + admins[_admin] = _isAdmin; + emit AdminSet(_admin, _isAdmin); + } + + // -------------------- Only Admin -------------------- + + /// @notice sets the default fee multiplier in basis points + /// @param _defaultMultiplierBps default fee multiplier + function setDefaultMultiplier(uint16 _defaultMultiplierBps) external onlyAdmin { + defaultMultiplierBps = _defaultMultiplierBps; + emit DefaultMultiplierSet(_defaultMultiplierBps); + } + + function setFeeLib(address _feeLib) external onlyAdmin { + feeLib = IDVNAdapterFeeLib(_feeLib); + emit FeeLibSet(_feeLib); + } + + /// @dev supports withdrawing fee from ULN301, ULN302 and more + /// @param _to address to withdraw fee to + /// @param _amount amount to withdraw + function withdrawFee(address _to, uint256 _amount) external onlyAdmin { + _withdrawFee(_to, _amount); + } + + /// @dev supports withdrawing token from the contract + /// @param _token token address + /// @param _to address to withdraw token to + /// @param _amount amount to withdraw + function withdrawToken(address _token, address _to, uint256 _amount) external onlyAdmin { + // transfers native if _token is address(0x0) + Transfer.nativeOrToken(_token, _to, _amount); + emit TokenWithdrawn(_to, _token, _amount); + } + + // -------------------- Internal Functions -------------------- + + function _assertBalanceAndWithdrawFee(uint256 _messageFee) internal { + uint256 balance = address(this).balance; + + if (balance < _messageFee) { + // withdraw fees from the sendLib if balance is insufficient + // sendLib will revert if not enough fees were accumulated + _withdrawFee(address(this), _messageFee - balance); // todo: why not withdraw all fees from sendLib? so that dont need to withdraw every time + } + } + + function _withdrawFee(address _to, uint256 _amount) internal { + sendLib.withdrawFee(_to, _amount); + emit FeeWithdrawn(_to, _amount); + } + + function _encodePayload( + bytes memory _packetHeader, + bytes32 _payloadHash + ) internal pure returns (bytes memory payload) { + return abi.encodePacked(_packetHeader, _payloadHash); + } + + function _decodePayload( + bytes memory _payload + ) internal pure returns (bytes memory packetHeader, bytes32 payloadHash) { + if (_payload.length != PAYLOAD_SIZE) revert InvalidPayloadSize(); + uint256 start = 0; + packetHeader = _payload.slice(start, PACKET_HEADER_SIZE); + + start += PACKET_HEADER_SIZE; + payloadHash = _payload.toBytes32(start); + } + + function _verify(bytes memory _payload) internal { + (bytes memory packetHeader, bytes32 payloadHash) = _decodePayload(_payload); + receiveLib.verify(packetHeader, payloadHash, MAX_CONFIRMATIONS); + } + + receive() external payable {} +} diff --git a/messagelib/contracts/uln/dvn/adapters/DVNAdapterFeeLibBase.sol b/messagelib/contracts/uln/dvn/adapters/DVNAdapterFeeLibBase.sol new file mode 100644 index 0000000..6945a81 --- /dev/null +++ b/messagelib/contracts/uln/dvn/adapters/DVNAdapterFeeLibBase.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity 0.8.22; + +import { IDVNAdapterFeeLib } from "../../interfaces/IDVNAdapterFeeLib.sol"; + +contract DVNAdapterFeeLibBase is IDVNAdapterFeeLib { + uint16 internal constant BPS_DENOMINATOR = 10000; + + function getFee( + uint32 /*_dstEid*/, + address /*_sender*/, + uint16 _defaultMultiplierBps, + uint16 _multiplierBps, + uint256 _executionFee + ) public pure virtual returns (uint256 fee) { + uint256 multiplier = _multiplierBps == 0 ? _defaultMultiplierBps : _multiplierBps; + fee = (_executionFee * multiplier) / BPS_DENOMINATOR; + } +} diff --git a/messagelib/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapter.sol b/messagelib/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapter.sol new file mode 100644 index 0000000..05a26d8 --- /dev/null +++ b/messagelib/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapter.sol @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity 0.8.22; + +import { AxelarExecutable } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol"; +import { IAxelarGasService } from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol"; + +import { DVNAdapterBase } from "../DVNAdapterBase.sol"; + +contract AxelarDVNAdapter is AxelarExecutable, DVNAdapterBase { + struct DstConfigParam { + uint32 dstEid; + uint16 multiplierBps; + uint256 nativeGasFee; + string peer; + string chainName; + } + + struct DstFeeParam { + uint32 dstEid; + uint256 nativeGasFee; + } + + struct DstConfig { + uint256 nativeGasFee; + uint16 multiplierBps; + string peer; + string chainName; + } + + event DstConfigSet(DstConfigParam[] params); + event DstFeeSet(DstFeeParam[] params); + + IAxelarGasService public immutable gasService; + + mapping(uint32 dstEid => DstConfig config) public dstConfig; + mapping(string axelarChain => uint32 eid) public axelarChainToEid; + + constructor( + address _sendLib, + address _receiveLib, + address[] memory _admins, + address _gateway, + address _gasReceiver + ) AxelarExecutable(_gateway) DVNAdapterBase(_sendLib, _receiveLib, _admins) { + gasService = IAxelarGasService(_gasReceiver); + } + + /// @notice sets configuration (`nativeGasFee`, `multiplierBps`, `peer`, and `chainName`) for destination chains + /// @dev The `nativeGasFee` and `multiplierBps` can be updated separately using `setDstNativeGasFee` and `setDstMultiplier` functions + /// @param _params array of chain configurations + function setDstConfig(DstConfigParam[] calldata _params) external onlyAdmin { + for (uint256 i = 0; i < _params.length; i++) { + DstConfigParam calldata param = _params[i]; + + delete axelarChainToEid[dstConfig[param.dstEid].chainName]; + + axelarChainToEid[param.chainName] = param.dstEid; + dstConfig[param.dstEid] = DstConfig({ + nativeGasFee: param.nativeGasFee, + multiplierBps: param.multiplierBps, + peer: param.peer, + chainName: param.chainName + }); + } + + emit DstConfigSet(_params); + } + + /// @notice sets message fee in native gas for destination chains. + /// @dev Axelar does not support quoting fee onchain. Instead, the fee needs to be obtained off-chain by querying through the Axelar SDK. + /// @dev The fee may change over time when token prices change, requiring admins to monitor and make necessary updates to reflect the actual fee. + /// @dev Adding a buffer to the required fee is advisable. Any surplus fee will be refunded asynchronously if it exceeds the necessary amount. + /// https://docs.axelar.dev/dev/general-message-passing/gas-services/pay-gas + /// https://github.com/axelarnetwork/axelarjs/blob/070c8fe061f1082e79772fdc5c4675c0237bbba2/packages/api/src/axelar-query/isomorphic.ts#L54 + /// https://github.com/axelarnetwork/axelar-cgp-solidity/blob/d4536599321774927bf9716178a9e360f8e0efac/contracts/gas-service/AxelarGasService.sol#L403 + /// @param _params array of message fees for destination chains + function setDstNativeGasFee(DstFeeParam[] calldata _params) external onlyAdmin { + // TODO - can delete and call setDstConfig instead? + for (uint256 i = 0; i < _params.length; i++) { + DstFeeParam calldata param = _params[i]; + dstConfig[param.dstEid].nativeGasFee = param.nativeGasFee; + } + + emit DstFeeSet(_params); + } + + /// @notice sets fee multiplier in basis points for destination chains + /// @param _params array of multipliers for destination chains + function setDstMultiplier(DstMultiplierParam[] calldata _params) external onlyAdmin { + // TODO - can delete and call setDstConfig instead? + for (uint256 i = 0; i < _params.length; i++) { + DstMultiplierParam calldata param = _params[i]; + dstConfig[param.dstEid].multiplierBps = param.multiplierBps; + } + + emit DstMultiplierSet(_params); + } + + function assignJob( + AssignJobParam calldata _param, + bytes calldata /*_options*/ + ) external payable override onlySendLib returns (uint256 fee) { + DstConfig storage config = dstConfig[_param.dstEid]; + fee = config.nativeGasFee; + string memory dstChainName = config.chainName; + string memory dstPeer = config.peer; + bytes memory payload = _encodePayload(_param.packetHeader, _param.payloadHash); + + _assertBalanceAndWithdrawFee(fee); + + // https://docs.axelar.dev/dev/general-message-passing/gas-services/pay-gas#paynativegasforcontractcall + gasService.payNativeGasForContractCall{ value: fee }( + address(this), // sender + dstChainName, // destinationChain + dstPeer, // destinationAddress + payload, // payload + address(this) // refundAddress + ); + // https://docs.axelar.dev/dev/general-message-passing/gmp-messages#call-a-contract-on-chain-b-from-chain-a + gateway.callContract(dstChainName, dstPeer, payload); + + if (address(feeLib) != address(0)) { + fee = feeLib.getFee(_param.dstEid, _param.sender, defaultMultiplierBps, config.multiplierBps, fee); + } + } + + function getFee( + uint32 _dstEid, + uint64 /*_confirmations*/, + address _sender, + bytes calldata /*_options*/ + ) external view override returns (uint256 fee) { + DstConfig storage config = dstConfig[_dstEid]; + fee = config.nativeGasFee; + if (address(feeLib) != address(0)) { + fee = feeLib.getFee(_dstEid, _sender, defaultMultiplierBps, config.multiplierBps, fee); + } + } + + function _execute( + string calldata _sourceChain, + string calldata _sourceAddress, + bytes calldata _payload + ) internal override { + _assertPeer(_sourceChain, _sourceAddress); + _verify(_payload); + } + + function _assertPeer(string calldata _sourceChain, string calldata _sourceAddress) private view { + uint32 sourceEid = axelarChainToEid[_sourceChain]; + string memory sourcePeer = dstConfig[sourceEid].peer; + + if (keccak256(bytes(_sourceAddress)) != keccak256(bytes(sourcePeer))) revert Unauthorized(); + } +} diff --git a/messagelib/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapterFeeLib.sol b/messagelib/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapterFeeLib.sol new file mode 100644 index 0000000..fe941e4 --- /dev/null +++ b/messagelib/contracts/uln/dvn/adapters/axelar/AxelarDVNAdapterFeeLib.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity 0.8.22; + +import { DVNAdapterFeeLibBase } from "../DVNAdapterFeeLibBase.sol"; + +contract AxelarDVNAdapterFeeLib is DVNAdapterFeeLibBase {} diff --git a/messagelib/contracts/uln/interfaces/IDVNAdapterFeeLib.sol b/messagelib/contracts/uln/interfaces/IDVNAdapterFeeLib.sol new file mode 100644 index 0000000..c93847c --- /dev/null +++ b/messagelib/contracts/uln/interfaces/IDVNAdapterFeeLib.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.8.0; + +interface IDVNAdapterFeeLib { + function getFee( + uint32 _dstEid, + address _sender, + uint16 _defaultMultiplierBps, + uint16 _multiplierBps, + uint256 _executionFee + ) external view returns (uint256 fee); +} diff --git a/messagelib/contracts/uln/uln301/mocks/NonceContractMock.sol b/messagelib/contracts/uln/uln301/mocks/NonceContractMock.sol index 2dd7dd2..b54a28c 100644 --- a/messagelib/contracts/uln/uln301/mocks/NonceContractMock.sol +++ b/messagelib/contracts/uln/uln301/mocks/NonceContractMock.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; diff --git a/messagelib/foundry.toml b/messagelib/foundry.toml index 0a9254f..495358b 100644 --- a/messagelib/foundry.toml +++ b/messagelib/foundry.toml @@ -10,6 +10,7 @@ optimizer_runs = 20_000 allow_paths = [ "../.yarn/unplugged", + "../node_modules", "../protocol" ] @@ -27,4 +28,6 @@ remappings = [ 'hardhat-deploy/=node_modules/hardhat-deploy/', '@layerzerolabs/lz-evm-protocol-v2/=node_modules/@layerzerolabs/lz-evm-protocol-v2/', '@layerzerolabs/lz-evm-v1-0.7/=node_modules/@layerzerolabs/lz-evm-v1-0.7/', + '@axelar-network/axelar-gmp-sdk-solidity/=node_modules/@axelar-network/axelar-gmp-sdk-solidity/', + '@chainlink/contracts-ccip/=node_modules/@chainlink/contracts-ccip/', ] \ No newline at end of file diff --git a/messagelib/package.json b/messagelib/package.json index cc06bed..b4432be 100644 --- a/messagelib/package.json +++ b/messagelib/package.json @@ -18,6 +18,8 @@ "solidity-bytes-utils": "^0.8.0" }, "devDependencies": { + "@axelar-network/axelar-gmp-sdk-solidity": "^5.6.3", + "@chainlink/contracts-ccip": "^0.7.6", "hardhat-deploy": "^0.11.44", "rimraf": "^5.0.5" }, diff --git a/messagelib/test/DVNAdapterBase.t.sol b/messagelib/test/DVNAdapterBase.t.sol new file mode 100644 index 0000000..a56353c --- /dev/null +++ b/messagelib/test/DVNAdapterBase.t.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: UNLICENSE + +pragma solidity ^0.8.0; + +import { Test } from "forge-std/Test.sol"; + +import { ILayerZeroDVN } from "../contracts/uln/interfaces/ILayerZeroDVN.sol"; +import { DVNAdapterBase } from "../contracts/uln/dvn/adapters/DVNAdapterBase.sol"; +import { DVNAdapterFeeLibBase } from "../contracts/uln/dvn/adapters/DVNAdapterFeeLibBase.sol"; +import { SendLibMock } from "./mocks/SendLibMock.sol"; +import { ReceiveLibMock } from "./mocks/ReceiveLibMock.sol"; + +contract DVNAdapterBaseHarness is DVNAdapterBase { + constructor( + address _sendLib, + address _receiveLib, + address[] memory _admins + ) DVNAdapterBase(_sendLib, _receiveLib, _admins) {} + + function exposed_PACKET_HEADER_SIZE() external pure returns (uint256) { + return PACKET_HEADER_SIZE; + } + + function exposed_PAYLOAD_SIZE() external pure returns (uint256) { + return PAYLOAD_SIZE; + } + + function exposed_assertBalanceAndWithdrawFee(uint256 _messageFee) external { + _assertBalanceAndWithdrawFee(_messageFee); + } + + function exposed_encodePayload( + bytes memory _packetHeader, + bytes32 _payloadHash + ) external pure returns (bytes memory payload) { + return _encodePayload(_packetHeader, _payloadHash); + } + + function exposed_decodePayload(bytes memory _payload) external pure returns (bytes memory, bytes32) { + return _decodePayload(_payload); + } + + function assignJob(AssignJobParam calldata, bytes calldata) external payable returns (uint256) { + return 0; + } + + function getFee(uint32, uint64, address, bytes calldata) external pure returns (uint256) { + return 0; + } +} + +contract DVNAdapterFeeLib is DVNAdapterFeeLibBase {} + +contract DVNAdapterBaseTest is Test { + DVNAdapterBaseHarness dvnAdapter; + SendLibMock sendLib; + ReceiveLibMock receiveLib; + + address admin = address(0x01); + + function setUp() public { + address[] memory admins = new address[](1); + admins[0] = admin; + sendLib = new SendLibMock(); + receiveLib = new ReceiveLibMock(); + dvnAdapter = new DVNAdapterBaseHarness(address(sendLib), address(receiveLib), admins); + } + + function testFuzz_setAdmin(address newAdmin) public { + dvnAdapter.setAdmin(newAdmin, true); + assertEq(dvnAdapter.admins(newAdmin), true); + + dvnAdapter.setAdmin(newAdmin, false); + assertEq(dvnAdapter.admins(newAdmin), false); + } + + function test_setAdmin_notOwner_revert() public { + address newAdmin = vm.addr(1); + + vm.prank(admin); + vm.expectRevert(); + dvnAdapter.setAdmin(newAdmin, true); + } + + function testFuzz_setDefaultMultiplier(uint16 defaultMultiplierBps) public { + vm.prank(admin); + dvnAdapter.setDefaultMultiplier(defaultMultiplierBps); + + assertEq(dvnAdapter.defaultMultiplierBps(), defaultMultiplierBps); + } + + function testFuzz_setAdmin_notAdmin_revert(address caller, uint16 defaultMultiplierBps) public { + vm.assume(caller != admin); + + vm.prank(caller); + vm.expectRevert(DVNAdapterBase.Unauthorized.selector); + dvnAdapter.setDefaultMultiplier(defaultMultiplierBps); + } + + function test_setFeeLib() public { + DVNAdapterFeeLib feeLib = new DVNAdapterFeeLib(); + + vm.prank(admin); + dvnAdapter.setFeeLib(address(feeLib)); + + assertEq(address(dvnAdapter.feeLib()), address(feeLib)); + } + + function testFuzz_setFeeLib_notAdmin_revert(address caller) public { + vm.assume(caller != admin); + + DVNAdapterFeeLib feeLib = new DVNAdapterFeeLib(); + + vm.prank(caller); + vm.expectRevert(DVNAdapterBase.Unauthorized.selector); + dvnAdapter.setFeeLib(address(feeLib)); + } + + function testFuzz_withdrawFee(uint256 fee) public { + assertEq(address(dvnAdapter).balance, 0); + + vm.deal(admin, fee); + vm.prank(admin); + sendLib.setFee{ value: fee }(address(dvnAdapter)); + + vm.prank(admin); + dvnAdapter.withdrawFee(address(dvnAdapter), fee); + + assertEq(address(dvnAdapter).balance, fee); + } + + function testFuzz_assertBalanceAndWithdrawFee_sufficientBalance_noWithdraw(uint256 fee) public { + vm.deal(address(dvnAdapter), fee); + assertEq(address(dvnAdapter).balance, fee); + + dvnAdapter.exposed_assertBalanceAndWithdrawFee(fee); + assertEq(address(dvnAdapter).balance, fee); + } + + function testFuzz_assertBalanceAndWithdrawFee_insufficientBalance_withdraw(uint256 fee) public { + vm.deal(admin, fee); + vm.prank(admin); + sendLib.setFee{ value: fee }(address(dvnAdapter)); + assertEq(sendLib.fees(address(dvnAdapter)), fee); + assertEq(address(dvnAdapter).balance, 0); + + dvnAdapter.exposed_assertBalanceAndWithdrawFee(fee); + assertEq(address(dvnAdapter).balance, fee); + assertEq(sendLib.fees(address(dvnAdapter)), 0); + } + + function testFuzz_encodePayload(bytes memory packetHeader, bytes32 payloadHash) public { + vm.assume(packetHeader.length == dvnAdapter.exposed_PACKET_HEADER_SIZE()); + + bytes memory expected = abi.encodePacked(packetHeader, payloadHash); + bytes memory actual = dvnAdapter.exposed_encodePayload(packetHeader, payloadHash); + + assertEq(actual, expected); + } + + function testFuzz_decodePayload(bytes memory packetHeader, bytes32 payloadHash) public { + vm.assume(packetHeader.length == dvnAdapter.exposed_PACKET_HEADER_SIZE()); + + bytes memory payload = abi.encodePacked(packetHeader, payloadHash); + (bytes memory actualPacketHeader, bytes32 actualPayloadHash) = dvnAdapter.exposed_decodePayload(payload); + + assertEq(actualPacketHeader, packetHeader); + assertEq(actualPayloadHash, payloadHash); + } + + function testFuzz_decodePayload_invalidPayloadSize_revert(bytes memory payload) public { + vm.assume(payload.length != dvnAdapter.exposed_PAYLOAD_SIZE()); + + vm.expectRevert(DVNAdapterBase.InvalidPayloadSize.selector); + dvnAdapter.exposed_decodePayload(payload); + } +} diff --git a/messagelib/test/DVNAdapterFeeLibBase.t.sol b/messagelib/test/DVNAdapterFeeLibBase.t.sol new file mode 100644 index 0000000..a741800 --- /dev/null +++ b/messagelib/test/DVNAdapterFeeLibBase.t.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.22; + +import { Test } from "forge-std/Test.sol"; + +import { DVNAdapterFeeLibBase } from "../contracts/uln/dvn/adapters/DVNAdapterFeeLibBase.sol"; + +contract DVNAdapterFeeLibBaseTest is DVNAdapterFeeLibBase, Test { + uint256 constant MIN_EXECUTION_FEE = 0; + uint256 constant MAX_EXECUTION_FEE = 1 ether; + uint16 constant MAX_MULTIPLIER_BPS = 20000; + + function testFuzz_getFee_useDefaultMultiplier(uint16 defaultMultiplierBps, uint256 executionFee) public { + uint16 multiplierBps = 0; + defaultMultiplierBps = uint16(bound(defaultMultiplierBps, 0, MAX_MULTIPLIER_BPS)); + executionFee = bound(executionFee, MIN_EXECUTION_FEE, MAX_EXECUTION_FEE); + + uint256 actual = getFee(0, address(0), defaultMultiplierBps, multiplierBps, executionFee); + uint256 expected = (executionFee * defaultMultiplierBps) / BPS_DENOMINATOR; + + assertEq(actual, expected); + } + + function testFuzz_getFee_useMultiplier(uint16 multiplierBps, uint256 executionFee) public { + uint16 defaultMultiplierBps = 12000; + multiplierBps = uint16(bound(defaultMultiplierBps, 1, MAX_MULTIPLIER_BPS)); + executionFee = bound(executionFee, MIN_EXECUTION_FEE, MAX_EXECUTION_FEE); + + uint256 actual = getFee(0, address(0), defaultMultiplierBps, multiplierBps, executionFee); + uint256 expected = (executionFee * multiplierBps) / BPS_DENOMINATOR; + + assertEq(actual, expected); + } +} diff --git a/messagelib/test/mocks/ReceiveLibMock.sol b/messagelib/test/mocks/ReceiveLibMock.sol new file mode 100644 index 0000000..421b08f --- /dev/null +++ b/messagelib/test/mocks/ReceiveLibMock.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.22; + +import { SetConfigParam } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol"; +import { IMessageLib, MessageLibType } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol"; +import { IReceiveUlnE2 } from "../../contracts/uln/interfaces/IReceiveUlnE2.sol"; +import { Verification, VerificationState } from "../../contracts/uln/ReceiveUlnBase.sol"; + +contract ReceiveLibMock is IReceiveUlnE2, IMessageLib { + error NotImplemented(); + + mapping(bytes32 headerHash => mapping(bytes32 payloadHash => mapping(address dvn => Verification))) + public hashLookup; + + function verify(bytes calldata _packetHeader, bytes32 _payloadHash, uint64 _confirmations) external { + hashLookup[keccak256(_packetHeader)][_payloadHash][msg.sender] = Verification(true, _confirmations); + } + + function version() external pure returns (uint64 major, uint8 minor, uint8 endpointVersion) { + return (3, 0, 2); + } + + function verifiable(bytes calldata, bytes32) external pure returns (VerificationState) { + revert NotImplemented(); + } + + function commitVerification(bytes calldata, bytes32) external pure { + revert NotImplemented(); + } + + function setConfig(address, SetConfigParam[] calldata) external pure { + revert NotImplemented(); + } + + function getConfig(uint32, address, uint32) external pure returns (bytes memory) { + revert NotImplemented(); + } + + function isSupportedEid(uint32) external pure returns (bool) { + revert NotImplemented(); + } + + function messageLibType() external pure returns (MessageLibType) { + revert NotImplemented(); + } + + function supportsInterface(bytes4) external pure returns (bool) { + revert NotImplemented(); + } +} diff --git a/messagelib/test/mocks/SendLibMock.sol b/messagelib/test/mocks/SendLibMock.sol new file mode 100644 index 0000000..8a57254 --- /dev/null +++ b/messagelib/test/mocks/SendLibMock.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: UNLICENSED + +pragma solidity ^0.8.22; + +import { SetConfigParam } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLibManager.sol"; +import { MessagingFee } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; +import { MessageLibType } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/IMessageLib.sol"; +import { ISendLib, Packet } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ISendLib.sol"; +import { Transfer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/libs/Transfer.sol"; + +contract SendLibMock is ISendLib { + mapping(address worker => uint256) public fees; + + error InvalidAmount(uint256 requested, uint256 available); + error NotImplemented(); + + receive() external payable {} + + function setFee(address _worker) external payable { + fees[_worker] = msg.value; + } + + function _debitFee(uint256 _amount) internal { + uint256 fee = fees[msg.sender]; + if (_amount > fee) revert InvalidAmount(_amount, fee); + unchecked { + fees[msg.sender] = fee - _amount; + } + } + + function withdrawFee(address _to, uint256 _amount) external { + _debitFee(_amount); + address nativeToken = address(0); + Transfer.nativeOrToken(nativeToken, _to, _amount); + } + + function version() external pure returns (uint64 major, uint8 minor, uint8 endpointVersion) { + return (3, 0, 2); + } + + function send(Packet calldata, bytes calldata, bool) external pure returns (MessagingFee memory, bytes memory) { + revert NotImplemented(); + } + + function quote(Packet calldata, bytes calldata, bool) external pure returns (MessagingFee memory) { + revert NotImplemented(); + } + + function setTreasury(address) external pure { + revert NotImplemented(); + } + + function withdrawLzTokenFee(address, address, uint256) external pure { + revert NotImplemented(); + } + + function setConfig(address, SetConfigParam[] calldata) external pure { + revert NotImplemented(); + } + + function getConfig(uint32, address, uint32) external pure returns (bytes memory) { + revert NotImplemented(); + } + + function isSupportedEid(uint32) external pure returns (bool) { + revert NotImplemented(); + } + + function messageLibType() external pure returns (MessageLibType) { + revert NotImplemented(); + } + + function supportsInterface(bytes4) external pure returns (bool) { + revert NotImplemented(); + } +} diff --git a/oapp/contracts/oapp/OApp.sol b/oapp/contracts/oapp/OApp.sol index 5ced124..6759549 100644 --- a/oapp/contracts/oapp/OApp.sol +++ b/oapp/contracts/oapp/OApp.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { OAppSender } from "./OAppSender.sol"; diff --git a/oapp/contracts/oapp/OAppCore.sol b/oapp/contracts/oapp/OAppCore.sol index e650cf1..3efd9d8 100644 --- a/oapp/contracts/oapp/OAppCore.sol +++ b/oapp/contracts/oapp/OAppCore.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/oapp/contracts/oapp/OAppReceiver.sol b/oapp/contracts/oapp/OAppReceiver.sol index 1451d12..cfe957d 100644 --- a/oapp/contracts/oapp/OAppReceiver.sol +++ b/oapp/contracts/oapp/OAppReceiver.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { ILayerZeroReceiver, Origin } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroReceiver.sol"; diff --git a/oapp/contracts/oapp/OAppSender.sol b/oapp/contracts/oapp/OAppSender.sol index b23975f..683f8a4 100644 --- a/oapp/contracts/oapp/OAppSender.sol +++ b/oapp/contracts/oapp/OAppSender.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { SafeERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/oapp/contracts/oapp/examples/ExampleOApp.sol b/oapp/contracts/oapp/examples/ExampleOApp.sol index 76b0889..170261e 100644 --- a/oapp/contracts/oapp/examples/ExampleOApp.sol +++ b/oapp/contracts/oapp/examples/ExampleOApp.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { OApp, Origin } from "../OApp.sol"; diff --git a/oapp/contracts/oapp/examples/ExampleOAppPreCrimeSimulator.sol b/oapp/contracts/oapp/examples/ExampleOAppPreCrimeSimulator.sol index 05adaf7..3969c51 100644 --- a/oapp/contracts/oapp/examples/ExampleOAppPreCrimeSimulator.sol +++ b/oapp/contracts/oapp/examples/ExampleOAppPreCrimeSimulator.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { OApp, Origin } from "../OApp.sol"; diff --git a/oapp/contracts/oapp/examples/ExampleOAppReceiver.sol b/oapp/contracts/oapp/examples/ExampleOAppReceiver.sol index f135346..2b3e45a 100644 --- a/oapp/contracts/oapp/examples/ExampleOAppReceiver.sol +++ b/oapp/contracts/oapp/examples/ExampleOAppReceiver.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { OAppReceiver, OAppCore, Origin } from "../OAppReceiver.sol"; diff --git a/oapp/contracts/oapp/examples/ExampleOAppSender.sol b/oapp/contracts/oapp/examples/ExampleOAppSender.sol index 6ba975b..5e429bf 100644 --- a/oapp/contracts/oapp/examples/ExampleOAppSender.sol +++ b/oapp/contracts/oapp/examples/ExampleOAppSender.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { OAppSender, OAppCore } from "../OAppSender.sol"; diff --git a/oapp/contracts/oapp/examples/OmniCounter.sol b/oapp/contracts/oapp/examples/OmniCounter.sol index 17889c7..819e7a3 100644 --- a/oapp/contracts/oapp/examples/OmniCounter.sol +++ b/oapp/contracts/oapp/examples/OmniCounter.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; diff --git a/oapp/contracts/oapp/examples/OmniCounterPreCrime.sol b/oapp/contracts/oapp/examples/OmniCounterPreCrime.sol index ae9fa7a..7e9b2aa 100644 --- a/oapp/contracts/oapp/examples/OmniCounterPreCrime.sol +++ b/oapp/contracts/oapp/examples/OmniCounterPreCrime.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; diff --git a/oapp/contracts/oapp/interfaces/IOAppComposer.sol b/oapp/contracts/oapp/interfaces/IOAppComposer.sol index 75b508a..2f4d7ec 100644 --- a/oapp/contracts/oapp/interfaces/IOAppComposer.sol +++ b/oapp/contracts/oapp/interfaces/IOAppComposer.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { ILayerZeroComposer } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol"; diff --git a/oapp/contracts/oapp/interfaces/IOAppCore.sol b/oapp/contracts/oapp/interfaces/IOAppCore.sol index 36a29cc..f72d9da 100644 --- a/oapp/contracts/oapp/interfaces/IOAppCore.sol +++ b/oapp/contracts/oapp/interfaces/IOAppCore.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { ILayerZeroEndpointV2 } from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroEndpointV2.sol"; diff --git a/oapp/contracts/oapp/interfaces/IOAppMsgInspector.sol b/oapp/contracts/oapp/interfaces/IOAppMsgInspector.sol index 9bb0565..00a1a57 100644 --- a/oapp/contracts/oapp/interfaces/IOAppMsgInspector.sol +++ b/oapp/contracts/oapp/interfaces/IOAppMsgInspector.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; interface IOAppMsgInspector { diff --git a/oapp/contracts/oapp/interfaces/IOAppOptionsType3.sol b/oapp/contracts/oapp/interfaces/IOAppOptionsType3.sol index 2160136..0cc09b4 100644 --- a/oapp/contracts/oapp/interfaces/IOAppOptionsType3.sol +++ b/oapp/contracts/oapp/interfaces/IOAppOptionsType3.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; struct EnforcedOptionParam { diff --git a/oapp/contracts/oapp/libs/OAppOptionsType3.sol b/oapp/contracts/oapp/libs/OAppOptionsType3.sol index 701fe26..23348e4 100644 --- a/oapp/contracts/oapp/libs/OAppOptionsType3.sol +++ b/oapp/contracts/oapp/libs/OAppOptionsType3.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/oapp/contracts/oapp/libs/OptionsBuilder.sol b/oapp/contracts/oapp/libs/OptionsBuilder.sol index 6a9d23e..197aba8 100644 --- a/oapp/contracts/oapp/libs/OptionsBuilder.sol +++ b/oapp/contracts/oapp/libs/OptionsBuilder.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; diff --git a/oapp/contracts/oft/OFT.sol b/oapp/contracts/oft/OFT.sol index 6d45507..c433b62 100644 --- a/oapp/contracts/oft/OFT.sol +++ b/oapp/contracts/oft/OFT.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; diff --git a/oapp/contracts/oft/OFTAdapter.sol b/oapp/contracts/oft/OFTAdapter.sol index 52d73cd..62b7ec6 100644 --- a/oapp/contracts/oft/OFTAdapter.sol +++ b/oapp/contracts/oft/OFTAdapter.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { IERC20Metadata, IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; diff --git a/oapp/contracts/oft/OFTCore.sol b/oapp/contracts/oft/OFTCore.sol index b5f390c..e604703 100644 --- a/oapp/contracts/oft/OFTCore.sol +++ b/oapp/contracts/oft/OFTCore.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { OApp, Origin } from "../oapp/OApp.sol"; diff --git a/oapp/contracts/oft/OFTPrecrime.sol b/oapp/contracts/oft/OFTPrecrime.sol index 257f1da..d894b88 100644 --- a/oapp/contracts/oft/OFTPrecrime.sol +++ b/oapp/contracts/oft/OFTPrecrime.sol @@ -1,4 +1,5 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; // import { IOApp } from "../../interfaces/IOApp.sol"; diff --git a/oapp/contracts/oft/extensions/Fee.sol b/oapp/contracts/oft/extensions/Fee.sol index 9eb9287..d756ab1 100644 --- a/oapp/contracts/oft/extensions/Fee.sol +++ b/oapp/contracts/oft/extensions/Fee.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/oapp/contracts/oft/interfaces/IOFT.sol b/oapp/contracts/oft/interfaces/IOFT.sol index f3121ff..4c2e335 100644 --- a/oapp/contracts/oft/interfaces/IOFT.sol +++ b/oapp/contracts/oft/interfaces/IOFT.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { MessagingReceipt, MessagingFee } from "../../oapp/OAppSender.sol"; diff --git a/oapp/contracts/oft/libs/OFTComposeMsgCodec.sol b/oapp/contracts/oft/libs/OFTComposeMsgCodec.sol index 84c28cd..bc46dab 100644 --- a/oapp/contracts/oft/libs/OFTComposeMsgCodec.sol +++ b/oapp/contracts/oft/libs/OFTComposeMsgCodec.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; library OFTComposeMsgCodec { diff --git a/oapp/contracts/oft/libs/OFTMsgCodec.sol b/oapp/contracts/oft/libs/OFTMsgCodec.sol index ac820f6..782f1e1 100644 --- a/oapp/contracts/oft/libs/OFTMsgCodec.sol +++ b/oapp/contracts/oft/libs/OFTMsgCodec.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; library OFTMsgCodec { diff --git a/oapp/contracts/precrime/OAppPreCrimeSimulator.sol b/oapp/contracts/precrime/OAppPreCrimeSimulator.sol index d342ce6..d3a5276 100644 --- a/oapp/contracts/precrime/OAppPreCrimeSimulator.sol +++ b/oapp/contracts/precrime/OAppPreCrimeSimulator.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/oapp/contracts/precrime/PreCrime.sol b/oapp/contracts/precrime/PreCrime.sol index b1cddcb..f2e5802 100644 --- a/oapp/contracts/precrime/PreCrime.sol +++ b/oapp/contracts/precrime/PreCrime.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; diff --git a/oapp/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol b/oapp/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol index 406ccc2..020338b 100644 --- a/oapp/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol +++ b/oapp/contracts/precrime/interfaces/IOAppPreCrimeSimulator.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; import { InboundPacket, Origin } from "../libs/Packet.sol"; diff --git a/oapp/contracts/precrime/interfaces/IPreCrime.sol b/oapp/contracts/precrime/interfaces/IPreCrime.sol index b0ac424..92310ec 100644 --- a/oapp/contracts/precrime/interfaces/IPreCrime.sol +++ b/oapp/contracts/precrime/interfaces/IPreCrime.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.22; struct PreCrimePeer { uint32 eid; diff --git a/oapp/contracts/precrime/libs/Packet.sol b/oapp/contracts/precrime/libs/Packet.sol index b239da5..a990194 100644 --- a/oapp/contracts/precrime/libs/Packet.sol +++ b/oapp/contracts/precrime/libs/Packet.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; diff --git a/oapp/foundry.toml b/oapp/foundry.toml index 2017f2a..fa1ba0c 100644 --- a/oapp/foundry.toml +++ b/oapp/foundry.toml @@ -10,6 +10,7 @@ optimizer_runs = 20_000 allow_paths = [ "../.yarn/unplugged", + "../node_modules", "../protocol", "../messagelib" ] diff --git a/package.json b/package.json index a2809fa..60d5083 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,12 @@ "solhint": "^4.0.0" }, "dependenciesMeta": { + "@axelar-network/axelar-gmp-sdk-solidity": { + "unplugged": true + }, + "@chainlink/contracts-ccip": { + "unplugged": true + }, "@layerzerolabs/lz-evm-v1-0.7": { "unplugged": true }, diff --git a/protocol/contracts/messagelib/libs/BitMaps.sol b/protocol/contracts/messagelib/libs/BitMaps.sol index e7b52bd..944b28e 100644 --- a/protocol/contracts/messagelib/libs/BitMaps.sol +++ b/protocol/contracts/messagelib/libs/BitMaps.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: BUSL-1.1 +// SPDX-License-Identifier: MIT // modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/BitMaps.sol pragma solidity ^0.8.22; diff --git a/protocol/foundry.toml b/protocol/foundry.toml index 9ee3006..1b29233 100644 --- a/protocol/foundry.toml +++ b/protocol/foundry.toml @@ -10,6 +10,7 @@ optimizer_runs = 20_000 allow_paths = [ "../.yarn/unplugged", + "../node_modules", ] libs = [ diff --git a/yarn.lock b/yarn.lock index 89f1dd5..dde2ce9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,6 +5,13 @@ __metadata: version: 8 cacheKey: 10 +"@axelar-network/axelar-gmp-sdk-solidity@npm:^5.6.3": + version: 5.6.4 + resolution: "@axelar-network/axelar-gmp-sdk-solidity@npm:5.6.4" + checksum: 94443f7250fbdd046239f03fbf83489a3ee9aceeb02f76c177ae0e522a16be4b202c386bd1aaa3bd7bdc1e6c57b92d7fee8e8bd8a063f244d454a1fab8d86ddf + languageName: node + linkType: hard + "@babel/code-frame@npm:^7.0.0": version: 7.23.5 resolution: "@babel/code-frame@npm:7.23.5" @@ -134,6 +141,18 @@ __metadata: languageName: node linkType: hard +"@chainlink/contracts-ccip@npm:^0.7.6": + version: 0.7.6 + resolution: "@chainlink/contracts-ccip@npm:0.7.6" + dependencies: + "@eth-optimism/contracts": "npm:^0.5.21" + "@openzeppelin/contracts": "npm:~4.3.3" + "@openzeppelin/contracts-upgradeable-4.7.3": "npm:@openzeppelin/contracts-upgradeable@v4.7.3" + "@openzeppelin/contracts-v0.7": "npm:@openzeppelin/contracts@v3.4.2" + checksum: 1a2daf828c72ad0ff192d3c9c0d8517be17fc4e6c44db5d90a4f40a7a7104844d184ad2cc0873acdaee7b8cb020d343dadd1d9cb883de90c1f60ec37bcc68d34 + languageName: node + linkType: hard + "@chainsafe/as-sha256@npm:^0.3.1": version: 0.3.1 resolution: "@chainsafe/as-sha256@npm:0.3.1" @@ -180,6 +199,43 @@ __metadata: languageName: node linkType: hard +"@eth-optimism/contracts@npm:^0.5.21": + version: 0.5.40 + resolution: "@eth-optimism/contracts@npm:0.5.40" + dependencies: + "@eth-optimism/core-utils": "npm:0.12.0" + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + peerDependencies: + ethers: ^5 + checksum: 5333f7d5792ad7c656202ce6e9e875993da7423b670f3da5e1cee9330d6c29b4f102ecc2fee06ca353381a2e603485e8a883e8a3979218effec2ead84f46e9a2 + languageName: node + linkType: hard + +"@eth-optimism/core-utils@npm:0.12.0": + version: 0.12.0 + resolution: "@eth-optimism/core-utils@npm:0.12.0" + dependencies: + "@ethersproject/abi": "npm:^5.7.0" + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/contracts": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/providers": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/web": "npm:^5.7.0" + bufio: "npm:^1.0.7" + chai: "npm:^4.3.4" + checksum: a7ea17a8b529b2c86b00ef19fa562c2b792d7e8a4071defea4d8a8b82a101105a3ab6dc86361118e17bf9b4784b4eca9c1e937c8b1e7294a1a850f97b5a73a10 + languageName: node + linkType: hard + "@ethereumjs/common@npm:2.5.0": version: 2.5.0 resolution: "@ethereumjs/common@npm:2.5.0" @@ -447,7 +503,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": +"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.0, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" dependencies: @@ -647,6 +703,8 @@ __metadata: version: 0.0.0-use.local resolution: "@layerzerolabs/lz-evm-messagelib-v2@workspace:messagelib" dependencies: + "@axelar-network/axelar-gmp-sdk-solidity": "npm:^5.6.3" + "@chainlink/contracts-ccip": "npm:^0.7.6" "@layerzerolabs/lz-evm-protocol-v2": "workspace:^" "@layerzerolabs/lz-evm-v1-0.7": "npm:^1.5.77" "@openzeppelin/contracts": "npm:^4.8.1" @@ -713,6 +771,10 @@ __metadata: rimraf: "npm:^5.0.5" solhint: "npm:^4.0.0" dependenciesMeta: + "@axelar-network/axelar-gmp-sdk-solidity": + unplugged: true + "@chainlink/contracts-ccip": + unplugged: true "@layerzerolabs/lz-evm-v1-0.7": unplugged: true "@layerzerolabs/solidity-examples": @@ -1110,6 +1172,13 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/contracts-upgradeable-4.7.3@npm:@openzeppelin/contracts-upgradeable@v4.7.3": + version: 4.7.3 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.7.3" + checksum: 7c72ffeca867478b5aa8e8c7adb3d1ce114cfdc797ed4f3cd074788cf4da25d620ffffd624ac7e9d1223eecffeea9f7b79200ff70dc464cc828c470ccd12ddf1 + languageName: node + linkType: hard + "@openzeppelin/contracts-upgradeable@npm:^4.8.1": version: 4.9.5 resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.5" @@ -1117,6 +1186,13 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/contracts-v0.7@npm:@openzeppelin/contracts@v3.4.2": + version: 3.4.2 + resolution: "@openzeppelin/contracts@npm:3.4.2" + checksum: e803e322bd111565e2de742c62f1a598c7c7dd7385c1c0fe3c06e2b4913e599024ad1d32e2693f199f5230af4d9b0eeefb389f32740006312895b962a4d937d4 + languageName: node + linkType: hard + "@openzeppelin/contracts@npm:^4.8.1": version: 4.9.4 resolution: "@openzeppelin/contracts@npm:4.9.4" @@ -1124,6 +1200,13 @@ __metadata: languageName: node linkType: hard +"@openzeppelin/contracts@npm:~4.3.3": + version: 4.3.3 + resolution: "@openzeppelin/contracts@npm:4.3.3" + checksum: 14fb7f3807054033671562165086ac4d1a500cf2068a6eadad16cbeb443df508a659cc658d91bf3ea0aea64920048cc26a7ad7d2a4f7844671e3084a4fc5cf0b + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -1764,6 +1847,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf + languageName: node + linkType: hard + "ast-parents@npm:^0.0.1": version: 0.0.1 resolution: "ast-parents@npm:0.0.1" @@ -2221,6 +2311,13 @@ __metadata: languageName: node linkType: hard +"bufio@npm:^1.0.7": + version: 1.2.1 + resolution: "bufio@npm:1.2.1" + checksum: c8920ee0d765eb97d218643705346c3360ae6227414df7b3f345932531b85d18fe385d0740e1bcda6225fa082a179910679f444a6de5aec7aecd176a01e40573 + languageName: node + linkType: hard + "bundle-name@npm:^3.0.0": version: 3.0.0 resolution: "bundle-name@npm:3.0.0" @@ -2361,6 +2458,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.3.4": + version: 4.3.10 + resolution: "chai@npm:4.3.10" + dependencies: + assertion-error: "npm:^1.1.0" + check-error: "npm:^1.0.3" + deep-eql: "npm:^4.1.3" + get-func-name: "npm:^2.0.2" + loupe: "npm:^2.3.6" + pathval: "npm:^1.1.1" + type-detect: "npm:^4.0.8" + checksum: 9e545fd60f5efee4f06f7ad62f7b1b142932b08fbb3454db69defd511e7c58771ce51843764212da1e129b2c9d1b029fbf5f98da030fe67a95a0853e8679524f + languageName: node + linkType: hard + "chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -2382,6 +2494,15 @@ __metadata: languageName: node linkType: hard +"check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: "npm:^2.0.2" + checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 + languageName: node + linkType: hard + "checkpoint-store@npm:^1.1.0": version: 1.1.0 resolution: "checkpoint-store@npm:1.1.0" @@ -2824,6 +2945,15 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^4.1.3": + version: 4.1.3 + resolution: "deep-eql@npm:4.1.3" + dependencies: + type-detect: "npm:^4.0.0" + checksum: 12ce93ae63de187e77b076d3d51bfc28b11f98910a22c18714cce112791195e86a94f97788180994614b14562a86c9763f67c69f785e4586f806b5df39bf9301 + languageName: node + linkType: hard + "deep-extend@npm:^0.6.0": version: 0.6.0 resolution: "deep-extend@npm:0.6.0" @@ -4033,6 +4163,13 @@ __metadata: languageName: node linkType: hard +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b + languageName: node + linkType: hard + "get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": version: 1.2.2 resolution: "get-intrinsic@npm:1.2.2" @@ -5343,6 +5480,15 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^2.3.6": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" + dependencies: + get-func-name: "npm:^2.0.1" + checksum: 635c8f0914c2ce7ecfe4e239fbaf0ce1d2c00e4246fafcc4ed000bfdb1b8f89d05db1a220054175cca631ebf3894872a26fffba0124477fcb562f78762848fb1 + languageName: node + linkType: hard + "lowercase-keys@npm:^2.0.0": version: 2.0.0 resolution: "lowercase-keys@npm:2.0.0" @@ -6380,6 +6526,13 @@ __metadata: languageName: node linkType: hard +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: b50a4751068aa3a5428f5a0b480deecedc6f537666a3630a0c2ae2d5e7c0f4bf0ee77b48404441ec1220bef0c91625e6030b3d3cf5a32ab0d9764018d1d9dbb6 + languageName: node + linkType: hard + "pbkdf2@npm:^3.0.17": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" @@ -7769,6 +7922,13 @@ __metadata: languageName: node linkType: hard +"type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 5179e3b8ebc51fce1b13efb75fdea4595484433f9683bbc2dca6d99789dba4e602ab7922d2656f2ce8383987467f7770131d4a7f06a26287db0615d2f4c4ce7d + languageName: node + linkType: hard + "type-fest@npm:^0.21.3": version: 0.21.3 resolution: "type-fest@npm:0.21.3"