From ac1c8741867393c92322d3e54ca73da0a19cc340 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Tue, 9 Apr 2024 00:08:05 -0400 Subject: [PATCH 01/28] WIP started working on Wormhole integration --- .env.example | 2 +- script/DeployEchoCC.s.sol | 23 +++++ script/TestEchoCC.s.sol | 22 +++++ src/CrossChainMessage.sol | 65 ++++++++++++++ src/CrossChainSupport.sol | 168 ++++++++++++++++++++++++++++++++++ src/EchoCC.sol | 80 +++++++++++++++++ src/wormhole/BytesLib.sol | 179 +++++++++++++++++++++++++++++++++++++ src/wormhole/IWormhole.sol | 146 ++++++++++++++++++++++++++++++ 8 files changed, 684 insertions(+), 1 deletion(-) create mode 100644 script/DeployEchoCC.s.sol create mode 100644 script/TestEchoCC.s.sol create mode 100644 src/CrossChainMessage.sol create mode 100644 src/CrossChainSupport.sol create mode 100644 src/EchoCC.sol create mode 100644 src/wormhole/BytesLib.sol create mode 100644 src/wormhole/IWormhole.sol diff --git a/.env.example b/.env.example index 167e6fd..59a8454 100644 --- a/.env.example +++ b/.env.example @@ -2,4 +2,4 @@ MAINNET_RPC_URL= SEPOLIA_RPC_URL= PRIVATE_KEY= MAINNET_PRIVATE_KEY= -ETHERSCAN_KEY= +ETHERSCAN_KEY= \ No newline at end of file diff --git a/script/DeployEchoCC.s.sol b/script/DeployEchoCC.s.sol new file mode 100644 index 0000000..5b49a25 --- /dev/null +++ b/script/DeployEchoCC.s.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Script.sol"; +import "../src/EchoCC.sol"; + +contract DeployEchoCC is Script { + // Exclude from coverage report + function test() public {} + + function run() external { + vm.startBroadcast(); + new EchoCC({ + owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), + signer: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), + wormhole: address(0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78), + chainId: 2, + wormholeFinality: 1 + }); + + vm.stopBroadcast(); + } +} diff --git a/script/TestEchoCC.s.sol b/script/TestEchoCC.s.sol new file mode 100644 index 0000000..b57652c --- /dev/null +++ b/script/TestEchoCC.s.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Script.sol"; +import "../src/EchoCC.sol"; + +contract TestEchoCC is Script { + // Exclude from coverage report + function test() public {} + + function run() external { + vm.startBroadcast(); + + // Use existing contract + EchoCC echo = EchoCC(0x7DA16cd402106Adaf39092215DbB54092b80B6E6); + + echo.registerEmitter(1, bytes32("echoSolanaAddress")); + echo.sendMessage("test"); + + vm.stopBroadcast(); + } +} diff --git a/src/CrossChainMessage.sol b/src/CrossChainMessage.sol new file mode 100644 index 0000000..917aaa4 --- /dev/null +++ b/src/CrossChainMessage.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "./wormhole/BytesLib.sol"; + +error InvalidPayloadId(); +error InvalidMessageLength(); + +struct EchoMessage { + // unique identifier for this message type + uint8 payloadID; + // arbitrary message string + string message; +} + +abstract contract CrossChainMessage { + using BytesLib for bytes; + + /** + * @notice Encodes the EchoMessage struct into bytes + * @param parsedMessage EchoMessage struct with arbitrary HelloWorld message + * @return encodedMessage EchoMessage encoded into bytes + */ + function encodeMessage(EchoMessage memory parsedMessage) public pure returns (bytes memory encodedMessage) { + // Convert message string to bytes so that we can use the .length attribute. + // The length of the arbitrary messages needs to be encoded in the message + // so that the corresponding decode function can decode the message properly. + bytes memory encodedMessagePayload = abi.encodePacked(parsedMessage.message); + + // return the encoded message + encodedMessage = + abi.encodePacked(parsedMessage.payloadID, uint16(encodedMessagePayload.length), encodedMessagePayload); + } + + /** + * @notice Decodes bytes into EchoMessage struct + * @dev Verifies the payloadID + * @param encodedMessage encoded arbitrary Echo message + * @return parsedMessage EchoMessage struct with arbitrary Echo message + */ + function decodeMessage(bytes memory encodedMessage) public pure returns (EchoMessage memory parsedMessage) { + // starting index for byte parsing + uint256 index = 0; + + // parse and verify the payloadID + parsedMessage.payloadID = encodedMessage.toUint8(index); + if (parsedMessage.payloadID != 1) { + revert InvalidPayloadId(); + } + index += 1; + + // parse the message string length + uint256 messageLength = encodedMessage.toUint16(index); + index += 2; + + // parse the message string + bytes memory messageBytes = encodedMessage.slice(index, messageLength); + parsedMessage.message = string(messageBytes); + index += messageLength; + + if (index != encodedMessage.length) { + revert InvalidMessageLength(); + } + } +} diff --git a/src/CrossChainSupport.sol b/src/CrossChainSupport.sol new file mode 100644 index 0000000..6d7d8c9 --- /dev/null +++ b/src/CrossChainSupport.sol @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "./CrossChainMessage.sol"; +import "./wormhole/BytesLib.sol"; +import "./wormhole/IWormhole.sol"; +import "solmate/auth/Owned.sol"; + +error InvalidWormholeConfig(); +error InvalidEmitterChainId(); +error InvalidEmitterAddress(); +error InvalidEmitter(); +error FailedParsingAndVerifyingVm(); +error MessageAlreadyConsumed(); +error MessageTooLong(); +error NotEnoughWormholeFees(); + +struct State { + // address of the Wormhole contract on this chain + address wormhole; + // Need to store the chain ID as it might differ from the real id + // I.e. Ethereum is chainId = 2 for Wormhole because Solana is chainId = 1 + uint16 chainId; + /** + * The number of block confirmations needed before the wormhole network + * will attest a message. + */ + uint8 wormholeFinality; + /** + * Wormhole chain ID to known emitter address mapping. xDapps using + * Wormhole should register all deployed contracts on each chain to + * verify that messages being consumed are from trusted contracts. + */ + mapping(uint16 => bytes32) registeredEmitters; + // verified message hash to received message mapping + mapping(bytes32 => string) receivedMessages; + // verified message hash to boolean + mapping(bytes32 => bool) consumedMessages; +} + +abstract contract CrossChainSupport is Owned, CrossChainMessage { + using BytesLib for bytes; + + State private _state; + + constructor(address wormhole_, uint16 _chainId, uint8 wormholeFinality_) { + if (wormhole_ == address(0)) { + revert InvalidWormholeConfig(); + } + if (_chainId == 0) { + revert InvalidWormholeConfig(); + } + if (wormholeFinality_ == 0) { + revert InvalidWormholeConfig(); + } + _state.wormhole = payable(wormhole_); + _state.chainId = _chainId; + _state.wormholeFinality = wormholeFinality_; + } + + function isMessageConsumed(bytes32 hash) public view returns (bool) { + return _state.consumedMessages[hash]; + } + + function wormholeContract() public view returns (IWormhole) { + return IWormhole(_state.wormhole); + } + + function _setEmitter(uint16 chainId, bytes32 emitter) internal { + _state.registeredEmitters[chainId] = emitter; + } + + function _consumeMessage(bytes32 hash, string memory message) internal { + _state.receivedMessages[hash] = message; + _state.consumedMessages[hash] = true; + } + + /** + * @notice Registers foreign emitters (Echo contracts) with this contract + * @dev Only the deployer (owner) can invoke this method + * @param emitterChainId Wormhole chainId of the contract being registered + * See https://book.wormhole.com/reference/contracts.html for more information. + * @param emitterAddress 32-byte address of the contract being registered. For EVM + * contracts the first 12 bytes should be zeros. + */ + function registerEmitter(uint16 emitterChainId, bytes32 emitterAddress) external onlyOwner { + // sanity check the emitterChainId and emitterAddress input values + if (emitterChainId == _state.chainId) { + revert InvalidEmitterChainId(); + } + if (emitterAddress == bytes32(0)) { + revert InvalidEmitterAddress(); + } + + _setEmitter(emitterChainId, emitterAddress); + } + + function verifyEmitter(IWormhole.VM memory vm) internal view returns (bool) { + return _state.registeredEmitters[vm.emitterChainId] == vm.emitterAddress; + } + + /** + * @notice Creates an arbitrary Echo message to be attested by the + * Wormhole guardians. + * @dev batchID is set to 0 to opt out of batching in future Wormhole versions. + * Reverts if: + * - caller doesn't pass enough value to pay the Wormhole network fee + * - `helloWorldMessage` length is >= max(uint16) + * @param echoMessage Arbitrary Echo string + * @return messageSequence Wormhole message sequence for this contract + */ + function sendMessage(string memory echoMessage) public payable returns (uint64 messageSequence) { + if (abi.encodePacked(echoMessage).length > type(uint16).max) { + revert MessageTooLong(); + } + + IWormhole wormhole = wormholeContract(); + uint256 wormholeFee = wormhole.messageFee(); + + if (msg.value != wormholeFee) { + revert NotEnoughWormholeFees(); + } + EchoMessage memory parsedMessage = EchoMessage({payloadID: uint8(1), message: echoMessage}); + + bytes memory encodedMessage = encodeMessage(parsedMessage); + + // Send the Echo message by calling publishMessage on the + // Wormhole core contract and paying the Wormhole protocol fee. + messageSequence = wormhole.publishMessage{value: wormholeFee}( + 0, // batchID + encodedMessage, + _state.wormholeFinality + ); + } + + /** + * @notice Consumes arbitrary HelloWorld messages sent by registered emitters + * @dev The arbitrary message is verified by the Wormhole core endpoint + * `verifyVM`. + * Reverts if: + * - `encodedMessage` is not attested by the Wormhole network + * - `encodedMessage` was sent by an unregistered emitter + * - `encodedMessage` was consumed already + * @param encodedMessage verified Wormhole message containing arbitrary + * HelloWorld message. + */ + function receiveMessage(bytes memory encodedMessage) public { + // call the Wormhole core contract to parse and verify the encodedMessage + (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = + wormholeContract().parseAndVerifyVM(encodedMessage); + + if (!valid) { + // TODO Add reason? + revert FailedParsingAndVerifyingVm(); + } + + if (!verifyEmitter(wormholeMessage)) { + revert InvalidEmitter(); + } + + EchoMessage memory parsedMessage = decodeMessage(wormholeMessage.payload); + + if (isMessageConsumed(wormholeMessage.hash)) { + revert MessageAlreadyConsumed(); + } + _consumeMessage(wormholeMessage.hash, parsedMessage.message); + } +} diff --git a/src/EchoCC.sol b/src/EchoCC.sol new file mode 100644 index 0000000..582bc7c --- /dev/null +++ b/src/EchoCC.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "./Admin.sol"; +import "./Banker.sol"; +import "./CrossChainSupport.sol"; +import "./Handler.sol"; +import "./Signer.sol"; +import "solmate/utils/ReentrancyGuard.sol"; + +error TradeAlreadyExist(); +error TradeHasExpired(); +error InvalidCreator(); +error InvalidAssets(); +error InvalidPayment(); + +contract EchoCC is ReentrancyGuard, Admin, Handler, Banker, Signer, CrossChainSupport { + event TradeExecuted(string id); + + constructor(address owner, address signer, address wormhole, uint16 chainId, uint8 wormholeFinality) + Admin(owner, signer) + CrossChainSupport(wormhole, chainId, wormholeFinality) + {} + + /// @dev Only executed trades are on chain to avoid replay attacks + /// Trades are mapped by id + mapping(string => bool) internal trades; + + function executeTrade(uint8 v, bytes32 r, bytes32 s, Signature calldata signatureData, Trade calldata trade) + external + payable + nonReentrant + notPaused + { + if (trades[trade.id]) { + revert TradeAlreadyExist(); + } + + if (trade.creator != msg.sender) { + revert InvalidCreator(); + } + + // We only check that length is not 0 here because we check the length in the transfer method + if (trade.creatorCollections.length == 0 || trade.counterpartyCollections.length == 0) { + revert InvalidAssets(); + } + + if (trade.expiresAt <= block.timestamp) { + revert TradeHasExpired(); + } + + if (msg.value != tradingFee) { + revert InvalidPayment(); + } + + _validateSignature(v, r, s, signatureData, signer); + _validateTrade(signatureData, trade); + + // Transfer creator's assets + _transferTokens({ + collections: trade.creatorCollections, + ids: trade.creatorIds, + from: trade.creator, + to: trade.counterparty + }); + + // Transfer counterparty's assets + _transferTokens({ + collections: trade.counterpartyCollections, + ids: trade.counterpartyIds, + from: trade.counterparty, + to: trade.creator + }); + + // Add trade to list to avoid replay and duplicates + trades[trade.id] = true; + + emit TradeExecuted(trade.id); + } +} diff --git a/src/wormhole/BytesLib.sol b/src/wormhole/BytesLib.sol new file mode 100644 index 0000000..fa7ee78 --- /dev/null +++ b/src/wormhole/BytesLib.sol @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: Unlicense +/* + * @title Solidity Bytes Arrays Utils + * @author Gonçalo Sá + * + * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. + * This is a reduced version of the library. + */ +pragma solidity >=0.8.0 <0.9.0; + +library BytesLib { + uint256 private constant freeMemoryPtr = 0x40; + uint256 private constant maskModulo32 = 0x1f; + /** + * Size of word read by `mload` instruction. + */ + uint256 private constant memoryWord = 32; + uint256 internal constant uint8Size = 1; + uint256 internal constant uint16Size = 2; + uint256 internal constant uint32Size = 4; + uint256 internal constant uint64Size = 8; + uint256 internal constant uint128Size = 16; + uint256 internal constant uint256Size = 32; + uint256 internal constant addressSize = 20; + /** + * Bits in 12 bytes. + */ + uint256 private constant bytes12Bits = 96; + + function slice(bytes memory buffer, uint256 startIndex, uint256 length) internal pure returns (bytes memory) { + unchecked { + require(length + 31 >= length, "slice_overflow"); + } + require(buffer.length >= startIndex + length, "slice_outOfBounds"); + + bytes memory tempBytes; + + assembly ("memory-safe") { + // Get a location of some free memory and store it in tempBytes as + // Solidity does for memory variables. + tempBytes := mload(freeMemoryPtr) + + switch iszero(length) + case 0 { + // The first word of the slice result is potentially a partial + // word read from the original array. To read it, we calculate + // the length of that partial word and start copying that many + // bytes into the array. The first word we copy will start with + // data we don't care about, but the last `lengthmod` bytes will + // land at the beginning of the contents of the new array. When + // we're done copying, we overwrite the full first word with + // the actual length of the slice. + let lengthmod := and(length, maskModulo32) + // The multiplication in the next line is necessary + // because when slicing multiples of 32 bytes (lengthmod == 0) + // the following copy loop was copying the origin's length + // and then ending prematurely not copying everything it should. + let startOffset := add(lengthmod, mul(memoryWord, iszero(lengthmod))) + + let dst := add(tempBytes, startOffset) + let end := add(dst, length) + + for { let src := add(add(buffer, startOffset), startIndex) } lt(dst, end) { + dst := add(dst, memoryWord) + src := add(src, memoryWord) + } { mstore(dst, mload(src)) } + + // Update free-memory pointer + // allocating the array padded to 32 bytes like the compiler does now + // Note that negating bitwise the `maskModulo32` produces a mask that aligns addressing to 32 bytes. + mstore(freeMemoryPtr, and(add(dst, maskModulo32), not(maskModulo32))) + } + //if we want a zero-length slice let's just return a zero-length array + default { mstore(freeMemoryPtr, add(tempBytes, memoryWord)) } + + // Store the length of the buffer + // We need to do it even if the length is zero because Solidity does not garbage collect + mstore(tempBytes, length) + } + + return tempBytes; + } + + function toAddress(bytes memory buffer, uint256 startIndex) internal pure returns (address) { + require(buffer.length >= startIndex + addressSize, "toAddress_outOfBounds"); + address tempAddress; + + assembly ("memory-safe") { + // We want to shift into the lower 12 bytes and leave the upper 12 bytes clear. + tempAddress := shr(bytes12Bits, mload(add(add(buffer, memoryWord), startIndex))) + } + + return tempAddress; + } + + function toUint8(bytes memory buffer, uint256 startIndex) internal pure returns (uint8) { + require(buffer.length > startIndex, "toUint8_outOfBounds"); + + // Note that `endIndex == startOffset` for a given buffer due to the 32 bytes at the start that store the length. + uint256 startOffset = startIndex + uint8Size; + uint8 tempUint; + assembly ("memory-safe") { + tempUint := mload(add(buffer, startOffset)) + } + return tempUint; + } + + function toUint16(bytes memory buffer, uint256 startIndex) internal pure returns (uint16) { + uint256 endIndex = startIndex + uint16Size; + require(buffer.length >= endIndex, "toUint16_outOfBounds"); + + uint16 tempUint; + assembly ("memory-safe") { + // Note that `endIndex == startOffset` for a given buffer due to the 32 bytes at the start that store the length. + tempUint := mload(add(buffer, endIndex)) + } + return tempUint; + } + + function toUint32(bytes memory buffer, uint256 startIndex) internal pure returns (uint32) { + uint256 endIndex = startIndex + uint32Size; + require(buffer.length >= endIndex, "toUint32_outOfBounds"); + + uint32 tempUint; + assembly ("memory-safe") { + // Note that `endIndex == startOffset` for a given buffer due to the 32 bytes at the start that store the length. + tempUint := mload(add(buffer, endIndex)) + } + return tempUint; + } + + function toUint64(bytes memory buffer, uint256 startIndex) internal pure returns (uint64) { + uint256 endIndex = startIndex + uint64Size; + require(buffer.length >= endIndex, "toUint64_outOfBounds"); + + uint64 tempUint; + assembly ("memory-safe") { + // Note that `endIndex == startOffset` for a given buffer due to the 32 bytes at the start that store the length. + tempUint := mload(add(buffer, endIndex)) + } + return tempUint; + } + + function toUint128(bytes memory buffer, uint256 startIndex) internal pure returns (uint128) { + uint256 endIndex = startIndex + uint128Size; + require(buffer.length >= endIndex, "toUint128_outOfBounds"); + + uint128 tempUint; + assembly ("memory-safe") { + // Note that `endIndex == startOffset` for a given buffer due to the 32 bytes at the start that store the length. + tempUint := mload(add(buffer, endIndex)) + } + return tempUint; + } + + function toUint256(bytes memory buffer, uint256 startIndex) internal pure returns (uint256) { + uint256 endIndex = startIndex + uint256Size; + require(buffer.length >= endIndex, "toUint256_outOfBounds"); + + uint256 tempUint; + assembly ("memory-safe") { + // Note that `endIndex == startOffset` for a given buffer due to the 32 bytes at the start that store the length. + tempUint := mload(add(buffer, endIndex)) + } + return tempUint; + } + + function toBytes32(bytes memory buffer, uint256 startIndex) internal pure returns (bytes32) { + uint256 endIndex = startIndex + uint256Size; + require(buffer.length >= endIndex, "toBytes32_outOfBounds"); + + bytes32 tempBytes32; + assembly ("memory-safe") { + // Note that `endIndex == startOffset` for a given buffer due to the 32 bytes at the start that store the length. + tempBytes32 := mload(add(buffer, endIndex)) + } + return tempBytes32; + } +} diff --git a/src/wormhole/IWormhole.sol b/src/wormhole/IWormhole.sol new file mode 100644 index 0000000..4526424 --- /dev/null +++ b/src/wormhole/IWormhole.sol @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: Apache 2 +pragma solidity ^0.8.18; + +interface IWormhole { + struct GuardianSet { + address[] keys; + uint32 expirationTime; + } + + struct Signature { + bytes32 r; + bytes32 s; + uint8 v; + uint8 guardianIndex; + } + + struct VM { + uint8 version; + uint32 timestamp; + uint32 nonce; + uint16 emitterChainId; + bytes32 emitterAddress; + uint64 sequence; + uint8 consistencyLevel; + bytes payload; + uint32 guardianSetIndex; + Signature[] signatures; + bytes32 hash; + } + + struct ContractUpgrade { + bytes32 module; + uint8 action; + uint16 chain; + address newContract; + } + + struct GuardianSetUpgrade { + bytes32 module; + uint8 action; + uint16 chain; + GuardianSet newGuardianSet; + uint32 newGuardianSetIndex; + } + + struct SetMessageFee { + bytes32 module; + uint8 action; + uint16 chain; + uint256 messageFee; + } + + struct TransferFees { + bytes32 module; + uint8 action; + uint16 chain; + uint256 amount; + bytes32 recipient; + } + + struct RecoverChainId { + bytes32 module; + uint8 action; + uint256 evmChainId; + uint16 newChainId; + } + + event LogMessagePublished( + address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel + ); + event ContractUpgraded(address indexed oldContract, address indexed newContract); + event GuardianSetAdded(uint32 indexed index); + + function publishMessage(uint32 nonce, bytes memory payload, uint8 consistencyLevel) + external + payable + returns (uint64 sequence); + + function initialize() external; + + function parseAndVerifyVM(bytes calldata encodedVM) + external + view + returns (VM memory vm, bool valid, string memory reason); + + function verifyVM(VM memory vm) external view returns (bool valid, string memory reason); + + function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) + external + pure + returns (bool valid, string memory reason); + + function parseVM(bytes memory encodedVM) external pure returns (VM memory vm); + + function quorum(uint256 numGuardians) external pure returns (uint256 numSignaturesRequiredForQuorum); + + function getGuardianSet(uint32 index) external view returns (GuardianSet memory); + + function getCurrentGuardianSetIndex() external view returns (uint32); + + function getGuardianSetExpiry() external view returns (uint32); + + function governanceActionIsConsumed(bytes32 hash) external view returns (bool); + + function isInitialized(address impl) external view returns (bool); + + function chainId() external view returns (uint16); + + function isFork() external view returns (bool); + + function governanceChainId() external view returns (uint16); + + function governanceContract() external view returns (bytes32); + + function messageFee() external view returns (uint256); + + function evmChainId() external view returns (uint256); + + function nextSequence(address emitter) external view returns (uint64); + + function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu); + + function parseGuardianSetUpgrade(bytes memory encodedUpgrade) + external + pure + returns (GuardianSetUpgrade memory gsu); + + function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf); + + function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf); + + function parseRecoverChainId(bytes memory encodedRecoverChainId) + external + pure + returns (RecoverChainId memory rci); + + function submitContractUpgrade(bytes memory _vm) external; + + function submitSetMessageFee(bytes memory _vm) external; + + function submitNewGuardianSet(bytes memory _vm) external; + + function submitTransferFees(bytes memory _vm) external; + + function submitRecoverChainId(bytes memory _vm) external; +} From c3b530995276b9a0763bc0f9b49e0301d9e60e8c Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Tue, 9 Apr 2024 21:15:03 -0400 Subject: [PATCH 02/28] added mint script --- script/DeployERC721.s.sol | 11 ++++------ script/MintNfts.s.sol | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 script/MintNfts.s.sol diff --git a/script/DeployERC721.s.sol b/script/DeployERC721.s.sol index 7e5c167..60fb3ad 100644 --- a/script/DeployERC721.s.sol +++ b/script/DeployERC721.s.sol @@ -11,14 +11,11 @@ contract DeployNFT is Script { function run() external { vm.startBroadcast(); - Mocked721 SORAS = new Mocked721({name: "Sora's Dreamworld", symbol: 'Sora'}); - SORAS.setBaseURI("https://sorasdreamworld.io/tokens/"); + Mocked721 YKPS = new Mocked721({name: "Kanpai Panda", symbol: "YKPS"}); + YKPS.setBaseURI("https://prod.kanpaidev.com/api/token/"); - Mocked721WithSuffix CREEPZ = new Mocked721WithSuffix({ - name: 'Creepz by OVERLORD', - symbol: 'CBC' - }); - CREEPZ.setBaseURI("ipfs://QmVRsXpYYp3qALoxjYUfNZAA6A28P86REKkoqadoXM5tLn/"); + Mocked721WithSuffix MAD = new Mocked721WithSuffix({name: "Mad Lads", symbol: "MAD"}); + MAD.setBaseURI("https://madlads.s3.us-west-2.amazonaws.com/json/"); vm.stopBroadcast(); } diff --git a/script/MintNfts.s.sol b/script/MintNfts.s.sol new file mode 100644 index 0000000..7576600 --- /dev/null +++ b/script/MintNfts.s.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Script.sol"; +import "../test/mock/Mocked721.t.sol"; + +contract MintNfts is Script { + // Exclude from coverage report + function test() public {} + + function run() external { + vm.startBroadcast(); + + // Use existing contract + Mocked721 YKPS = Mocked721(0xcFCEe3d83eac17bCaB91290c89f4B26Ce82f0238); + + YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 10); + YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 23); + YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 44); + YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 534); + YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 1203); + + YKPS.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 3); + YKPS.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 123); + YKPS.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 454); + + // Use existing contract + Mocked721 MAD = Mocked721(0xcb4d0fB16C735d2d41D050F14982fd782FA32a5B); + + MAD.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 31); + MAD.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 532); + MAD.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 123); + + MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 5); + MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 63); + MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 324); + MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 65); + MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 767); + + vm.stopBroadcast(); + } +} From c3f2c67a4d53319319b6dff54fbf29b7c684e8fa Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:50:55 -0400 Subject: [PATCH 03/28] WIP Wormhole POC --- foundry.toml | 5 + ...choCC.s.sol => DeployEchoCrossChain.s.sol} | 7 +- ...tEchoCC.s.sol => TestEchoCrossChain.s.sol} | 6 +- src/Admin.sol | 12 +- src/AdminSigner.sol | 35 ++++ src/Banker.sol | 3 +- src/CrossChainMessage.sol | 65 ------- src/CrossChainSupport.sol | 168 ------------------ src/Echo.sol | 12 +- src/EchoCC.sol | 80 --------- src/EchoCrossChain.sol | 117 ++++++++++++ src/MessageValidator.sol | 24 +++ src/Signer.sol | 4 +- src/TestEcho.sol | 2 +- src/escrow/Escrow.sol | 12 ++ src/escrow/EscrowData.sol | 23 +++ src/escrow/EscrowHandler.sol | 16 ++ src/escrow/EscrowState.sol | 9 + src/wormhole/Message.sol | 81 +++++++++ src/wormhole/WormholeData.sol | 34 ++++ src/wormhole/WormholeError.sol | 13 ++ src/wormhole/WormholeGovernance.sol | 100 +++++++++++ src/wormhole/WormholeState.sol | 71 ++++++++ 23 files changed, 557 insertions(+), 342 deletions(-) rename script/{DeployEchoCC.s.sol => DeployEchoCrossChain.s.sol} (75%) rename script/{TestEchoCC.s.sol => TestEchoCrossChain.s.sol} (69%) create mode 100644 src/AdminSigner.sol delete mode 100644 src/CrossChainMessage.sol delete mode 100644 src/CrossChainSupport.sol delete mode 100644 src/EchoCC.sol create mode 100644 src/EchoCrossChain.sol create mode 100644 src/MessageValidator.sol create mode 100644 src/escrow/Escrow.sol create mode 100644 src/escrow/EscrowData.sol create mode 100644 src/escrow/EscrowHandler.sol create mode 100644 src/escrow/EscrowState.sol create mode 100644 src/wormhole/Message.sol create mode 100644 src/wormhole/WormholeData.sol create mode 100644 src/wormhole/WormholeError.sol create mode 100644 src/wormhole/WormholeGovernance.sol create mode 100644 src/wormhole/WormholeState.sol diff --git a/foundry.toml b/foundry.toml index 233a736..bcc25c6 100644 --- a/foundry.toml +++ b/foundry.toml @@ -7,6 +7,11 @@ src = 'src' out = 'out' libs = ['lib'] +remappings = [ + "forge-std/=lib/forge-std/src/", + "contracts/=src/", +] + fuzz_runs = 1000 [profile.ci] diff --git a/script/DeployEchoCC.s.sol b/script/DeployEchoCrossChain.s.sol similarity index 75% rename from script/DeployEchoCC.s.sol rename to script/DeployEchoCrossChain.s.sol index 5b49a25..1ba94eb 100644 --- a/script/DeployEchoCC.s.sol +++ b/script/DeployEchoCrossChain.s.sol @@ -1,18 +1,17 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; +import "contracts/EchoCrossChain.sol"; import "forge-std/Script.sol"; -import "../src/EchoCC.sol"; -contract DeployEchoCC is Script { +contract DeployEchoCrossChain is Script { // Exclude from coverage report function test() public {} function run() external { vm.startBroadcast(); - new EchoCC({ + new EchoCrossChain({ owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), - signer: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), wormhole: address(0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78), chainId: 2, wormholeFinality: 1 diff --git a/script/TestEchoCC.s.sol b/script/TestEchoCrossChain.s.sol similarity index 69% rename from script/TestEchoCC.s.sol rename to script/TestEchoCrossChain.s.sol index b57652c..279a618 100644 --- a/script/TestEchoCC.s.sol +++ b/script/TestEchoCrossChain.s.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; +import "contracts/EchoCrossChain.sol"; import "forge-std/Script.sol"; -import "../src/EchoCC.sol"; contract TestEchoCC is Script { // Exclude from coverage report @@ -12,10 +12,10 @@ contract TestEchoCC is Script { vm.startBroadcast(); // Use existing contract - EchoCC echo = EchoCC(0x7DA16cd402106Adaf39092215DbB54092b80B6E6); + EchoCrossChain echo = EchoCrossChain(0x7DA16cd402106Adaf39092215DbB54092b80B6E6); echo.registerEmitter(1, bytes32("echoSolanaAddress")); - echo.sendMessage("test"); + // echo.sendMessage('test'); vm.stopBroadcast(); } diff --git a/src/Admin.sol b/src/Admin.sol index 2901abb..268fb33 100644 --- a/src/Admin.sol +++ b/src/Admin.sol @@ -7,29 +7,19 @@ error Paused(); error InvalidAddress(); /// @dev Handles ownable and pausable of contract. -/// Also manages the signer address to validate trades abstract contract Admin is Owned { bool public paused; - address public signer; - constructor(address owner, address _signer) Owned(owner) { - signer = _signer; - } + constructor(address owner) Owned(owner) {} function setPaused(bool _paused) external onlyOwner { paused = _paused; } - function setSigner(address _signer) external onlyOwner { - if (_signer == address(0)) revert InvalidAddress(); - signer = _signer; - } - modifier notPaused() { if (paused) { revert Paused(); } - _; } } diff --git a/src/AdminSigner.sol b/src/AdminSigner.sol new file mode 100644 index 0000000..0df5d03 --- /dev/null +++ b/src/AdminSigner.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "solmate/auth/Owned.sol"; + +error Paused(); +error InvalidAddress(); + +/// @dev Handles ownable and pausable of contract. +/// Also manages the signer address to validate trades +abstract contract AdminSigner is Owned { + bool public paused; + address public signer; + + constructor(address owner, address _signer) Owned(owner) { + signer = _signer; + } + + function setPaused(bool _paused) external onlyOwner { + paused = _paused; + } + + function setSigner(address _signer) external onlyOwner { + if (_signer == address(0)) revert InvalidAddress(); + signer = _signer; + } + + modifier notPaused() { + if (paused) { + revert Paused(); + } + + _; + } +} diff --git a/src/Banker.sol b/src/Banker.sol index 2cd68bb..05d5528 100644 --- a/src/Banker.sol +++ b/src/Banker.sol @@ -1,12 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "./Admin.sol"; import "solmate/auth/Owned.sol"; error WithdrawFailed(); -abstract contract Banker is Owned, Admin { +abstract contract Banker is Owned { uint256 public tradingFee = 0 ether; /// Withdraw all funds available diff --git a/src/CrossChainMessage.sol b/src/CrossChainMessage.sol deleted file mode 100644 index 917aaa4..0000000 --- a/src/CrossChainMessage.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "./wormhole/BytesLib.sol"; - -error InvalidPayloadId(); -error InvalidMessageLength(); - -struct EchoMessage { - // unique identifier for this message type - uint8 payloadID; - // arbitrary message string - string message; -} - -abstract contract CrossChainMessage { - using BytesLib for bytes; - - /** - * @notice Encodes the EchoMessage struct into bytes - * @param parsedMessage EchoMessage struct with arbitrary HelloWorld message - * @return encodedMessage EchoMessage encoded into bytes - */ - function encodeMessage(EchoMessage memory parsedMessage) public pure returns (bytes memory encodedMessage) { - // Convert message string to bytes so that we can use the .length attribute. - // The length of the arbitrary messages needs to be encoded in the message - // so that the corresponding decode function can decode the message properly. - bytes memory encodedMessagePayload = abi.encodePacked(parsedMessage.message); - - // return the encoded message - encodedMessage = - abi.encodePacked(parsedMessage.payloadID, uint16(encodedMessagePayload.length), encodedMessagePayload); - } - - /** - * @notice Decodes bytes into EchoMessage struct - * @dev Verifies the payloadID - * @param encodedMessage encoded arbitrary Echo message - * @return parsedMessage EchoMessage struct with arbitrary Echo message - */ - function decodeMessage(bytes memory encodedMessage) public pure returns (EchoMessage memory parsedMessage) { - // starting index for byte parsing - uint256 index = 0; - - // parse and verify the payloadID - parsedMessage.payloadID = encodedMessage.toUint8(index); - if (parsedMessage.payloadID != 1) { - revert InvalidPayloadId(); - } - index += 1; - - // parse the message string length - uint256 messageLength = encodedMessage.toUint16(index); - index += 2; - - // parse the message string - bytes memory messageBytes = encodedMessage.slice(index, messageLength); - parsedMessage.message = string(messageBytes); - index += messageLength; - - if (index != encodedMessage.length) { - revert InvalidMessageLength(); - } - } -} diff --git a/src/CrossChainSupport.sol b/src/CrossChainSupport.sol deleted file mode 100644 index 6d7d8c9..0000000 --- a/src/CrossChainSupport.sol +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "./CrossChainMessage.sol"; -import "./wormhole/BytesLib.sol"; -import "./wormhole/IWormhole.sol"; -import "solmate/auth/Owned.sol"; - -error InvalidWormholeConfig(); -error InvalidEmitterChainId(); -error InvalidEmitterAddress(); -error InvalidEmitter(); -error FailedParsingAndVerifyingVm(); -error MessageAlreadyConsumed(); -error MessageTooLong(); -error NotEnoughWormholeFees(); - -struct State { - // address of the Wormhole contract on this chain - address wormhole; - // Need to store the chain ID as it might differ from the real id - // I.e. Ethereum is chainId = 2 for Wormhole because Solana is chainId = 1 - uint16 chainId; - /** - * The number of block confirmations needed before the wormhole network - * will attest a message. - */ - uint8 wormholeFinality; - /** - * Wormhole chain ID to known emitter address mapping. xDapps using - * Wormhole should register all deployed contracts on each chain to - * verify that messages being consumed are from trusted contracts. - */ - mapping(uint16 => bytes32) registeredEmitters; - // verified message hash to received message mapping - mapping(bytes32 => string) receivedMessages; - // verified message hash to boolean - mapping(bytes32 => bool) consumedMessages; -} - -abstract contract CrossChainSupport is Owned, CrossChainMessage { - using BytesLib for bytes; - - State private _state; - - constructor(address wormhole_, uint16 _chainId, uint8 wormholeFinality_) { - if (wormhole_ == address(0)) { - revert InvalidWormholeConfig(); - } - if (_chainId == 0) { - revert InvalidWormholeConfig(); - } - if (wormholeFinality_ == 0) { - revert InvalidWormholeConfig(); - } - _state.wormhole = payable(wormhole_); - _state.chainId = _chainId; - _state.wormholeFinality = wormholeFinality_; - } - - function isMessageConsumed(bytes32 hash) public view returns (bool) { - return _state.consumedMessages[hash]; - } - - function wormholeContract() public view returns (IWormhole) { - return IWormhole(_state.wormhole); - } - - function _setEmitter(uint16 chainId, bytes32 emitter) internal { - _state.registeredEmitters[chainId] = emitter; - } - - function _consumeMessage(bytes32 hash, string memory message) internal { - _state.receivedMessages[hash] = message; - _state.consumedMessages[hash] = true; - } - - /** - * @notice Registers foreign emitters (Echo contracts) with this contract - * @dev Only the deployer (owner) can invoke this method - * @param emitterChainId Wormhole chainId of the contract being registered - * See https://book.wormhole.com/reference/contracts.html for more information. - * @param emitterAddress 32-byte address of the contract being registered. For EVM - * contracts the first 12 bytes should be zeros. - */ - function registerEmitter(uint16 emitterChainId, bytes32 emitterAddress) external onlyOwner { - // sanity check the emitterChainId and emitterAddress input values - if (emitterChainId == _state.chainId) { - revert InvalidEmitterChainId(); - } - if (emitterAddress == bytes32(0)) { - revert InvalidEmitterAddress(); - } - - _setEmitter(emitterChainId, emitterAddress); - } - - function verifyEmitter(IWormhole.VM memory vm) internal view returns (bool) { - return _state.registeredEmitters[vm.emitterChainId] == vm.emitterAddress; - } - - /** - * @notice Creates an arbitrary Echo message to be attested by the - * Wormhole guardians. - * @dev batchID is set to 0 to opt out of batching in future Wormhole versions. - * Reverts if: - * - caller doesn't pass enough value to pay the Wormhole network fee - * - `helloWorldMessage` length is >= max(uint16) - * @param echoMessage Arbitrary Echo string - * @return messageSequence Wormhole message sequence for this contract - */ - function sendMessage(string memory echoMessage) public payable returns (uint64 messageSequence) { - if (abi.encodePacked(echoMessage).length > type(uint16).max) { - revert MessageTooLong(); - } - - IWormhole wormhole = wormholeContract(); - uint256 wormholeFee = wormhole.messageFee(); - - if (msg.value != wormholeFee) { - revert NotEnoughWormholeFees(); - } - EchoMessage memory parsedMessage = EchoMessage({payloadID: uint8(1), message: echoMessage}); - - bytes memory encodedMessage = encodeMessage(parsedMessage); - - // Send the Echo message by calling publishMessage on the - // Wormhole core contract and paying the Wormhole protocol fee. - messageSequence = wormhole.publishMessage{value: wormholeFee}( - 0, // batchID - encodedMessage, - _state.wormholeFinality - ); - } - - /** - * @notice Consumes arbitrary HelloWorld messages sent by registered emitters - * @dev The arbitrary message is verified by the Wormhole core endpoint - * `verifyVM`. - * Reverts if: - * - `encodedMessage` is not attested by the Wormhole network - * - `encodedMessage` was sent by an unregistered emitter - * - `encodedMessage` was consumed already - * @param encodedMessage verified Wormhole message containing arbitrary - * HelloWorld message. - */ - function receiveMessage(bytes memory encodedMessage) public { - // call the Wormhole core contract to parse and verify the encodedMessage - (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = - wormholeContract().parseAndVerifyVM(encodedMessage); - - if (!valid) { - // TODO Add reason? - revert FailedParsingAndVerifyingVm(); - } - - if (!verifyEmitter(wormholeMessage)) { - revert InvalidEmitter(); - } - - EchoMessage memory parsedMessage = decodeMessage(wormholeMessage.payload); - - if (isMessageConsumed(wormholeMessage.hash)) { - revert MessageAlreadyConsumed(); - } - _consumeMessage(wormholeMessage.hash, parsedMessage.message); - } -} diff --git a/src/Echo.sol b/src/Echo.sol index 9a3e85c..067d340 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "./Admin.sol"; -import "./Banker.sol"; -import "./Handler.sol"; -import "./Signer.sol"; +import "contracts/AdminSigner.sol"; +import "contracts/Banker.sol"; +import "contracts/Handler.sol"; +import "contracts/Signer.sol"; import "solmate/utils/ReentrancyGuard.sol"; error TradeAlreadyExist(); @@ -13,10 +13,10 @@ error InvalidCreator(); error InvalidAssets(); error InvalidPayment(); -contract Echo is ReentrancyGuard, Admin, Handler, Banker, Signer { +contract Echo is ReentrancyGuard, AdminSigner, Handler, Banker, Signer { event TradeExecuted(string id); - constructor(address owner, address signer) Admin(owner, signer) {} + constructor(address owner, address signer) AdminSigner(owner, signer) {} /// @dev Only executed trades are on chain to avoid replay attacks /// Trades are mapped by id diff --git a/src/EchoCC.sol b/src/EchoCC.sol deleted file mode 100644 index 582bc7c..0000000 --- a/src/EchoCC.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "./Admin.sol"; -import "./Banker.sol"; -import "./CrossChainSupport.sol"; -import "./Handler.sol"; -import "./Signer.sol"; -import "solmate/utils/ReentrancyGuard.sol"; - -error TradeAlreadyExist(); -error TradeHasExpired(); -error InvalidCreator(); -error InvalidAssets(); -error InvalidPayment(); - -contract EchoCC is ReentrancyGuard, Admin, Handler, Banker, Signer, CrossChainSupport { - event TradeExecuted(string id); - - constructor(address owner, address signer, address wormhole, uint16 chainId, uint8 wormholeFinality) - Admin(owner, signer) - CrossChainSupport(wormhole, chainId, wormholeFinality) - {} - - /// @dev Only executed trades are on chain to avoid replay attacks - /// Trades are mapped by id - mapping(string => bool) internal trades; - - function executeTrade(uint8 v, bytes32 r, bytes32 s, Signature calldata signatureData, Trade calldata trade) - external - payable - nonReentrant - notPaused - { - if (trades[trade.id]) { - revert TradeAlreadyExist(); - } - - if (trade.creator != msg.sender) { - revert InvalidCreator(); - } - - // We only check that length is not 0 here because we check the length in the transfer method - if (trade.creatorCollections.length == 0 || trade.counterpartyCollections.length == 0) { - revert InvalidAssets(); - } - - if (trade.expiresAt <= block.timestamp) { - revert TradeHasExpired(); - } - - if (msg.value != tradingFee) { - revert InvalidPayment(); - } - - _validateSignature(v, r, s, signatureData, signer); - _validateTrade(signatureData, trade); - - // Transfer creator's assets - _transferTokens({ - collections: trade.creatorCollections, - ids: trade.creatorIds, - from: trade.creator, - to: trade.counterparty - }); - - // Transfer counterparty's assets - _transferTokens({ - collections: trade.counterpartyCollections, - ids: trade.counterpartyIds, - from: trade.counterparty, - to: trade.creator - }); - - // Add trade to list to avoid replay and duplicates - trades[trade.id] = true; - - emit TradeExecuted(trade.id); - } -} diff --git a/src/EchoCrossChain.sol b/src/EchoCrossChain.sol new file mode 100644 index 0000000..dd19f94 --- /dev/null +++ b/src/EchoCrossChain.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/Admin.sol"; +import "contracts/Banker.sol"; +import "contracts/Handler.sol"; +import "contracts/MessageValidator.sol"; +import "contracts/escrow/Escrow.sol"; +import "contracts/wormhole/WormholeGovernance.sol"; +import "solmate/utils/ReentrancyGuard.sol"; + +error OfferAlreadyExist(); +error OfferHasExpired(); +error InvalidOfferStatus(); +error InvalidCounterparty(); +error InvalidAssets(); +error InvalidPayment(); + +contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGovernance, MessageValidator { + event TradeExecuted(string id); + + constructor(address owner, address wormhole, uint16 chainId, uint8 wormholeFinality) + Admin(owner) + WormholeGovernance(wormhole, chainId, wormholeFinality) + {} + + // @dev This function assumes that the offer was created on another chain. + function acceptOffer(string calldata offerId, Offer calldata offer, bytes calldata encodedMessage) + external + payable + nonReentrant + notPaused + { + if (_offers[offerId].sender == address(0)) { + revert OfferAlreadyExist(); + } + // @dev + if (offer.receiver != msg.sender) { + revert InvalidCounterparty(); + } + + if (offer.expiresAt <= block.timestamp) { + revert OfferHasExpired(); + } + + if (offer.status != OfferStatus.Created) { + revert InvalidOfferStatus(); + } + + // Validate that the offer was created on the other chain + // @dev This function will revert if not + EchoMessage memory message = _receiveMessage(encodedMessage); + _validateMessage(message, offer); + + _depositForReceiver(offer); + _offers[offerId] = offer; + + // @dev FIXME the message should change + EchoMessageWithoutPayload memory newMessage = EchoMessageWithoutPayload({ + id: message.id, + evmSender: message.evmSender, + evmReceiver: message.evmReceiver, + evmTokenAddress: message.evmTokenAddress, + evmTokenId: message.evmTokenId, + solSender: message.solSender, + solReceiver: message.solReceiver, + solSenderTokenMint: message.solSenderTokenMint + }); + _sendMessage(newMessage); + } + + function executeTrade() external payable nonReentrant notPaused { + // if (trades[trade.id]) { + // revert TradeAlreadyExist(); + // } + // + // if (trade.creator != msg.sender) { + // revert InvalidCreator(); + // } + // + // // We only check that length is not 0 here because we check the length in the transfer method + // if (trade.creatorCollections.length == 0 || trade.counterpartyCollections.length == 0) { + // revert InvalidAssets(); + // } + // + // if (trade.expiresAt <= block.timestamp) { + // revert TradeHasExpired(); + // } + // + // if (msg.value != tradingFee) { + // revert InvalidPayment(); + // } + // + // _validateSignature(v, r, s, signatureData, signer); + // _validateTrade(signatureData, trade); + // + // // Transfer creator's assets + // _transferTokens({ + // collections: trade.creatorCollections, + // ids: trade.creatorIds, + // from: trade.creator, + // to: trade.counterparty + // }); + // + // // Transfer counterparty's assets + // _transferTokens({ + // collections: trade.counterpartyCollections, + // ids: trade.counterpartyIds, + // from: trade.counterparty, + // to: trade.creator + // }); + // + // // Add trade to list to avoid replay and duplicates + // trades[trade.id] = true; + // emit TradeExecuted(trade.id); + } +} diff --git a/src/MessageValidator.sol b/src/MessageValidator.sol new file mode 100644 index 0000000..c8cd895 --- /dev/null +++ b/src/MessageValidator.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/escrow/EscrowData.sol"; +import "contracts/wormhole/WormholeData.sol"; + +error InvalidMessage(); + +abstract contract MessageValidator { + function _validateMessage(EchoMessage memory message, Offer calldata offer) internal { + if (address(uint160(uint256(message.evmSender))) != offer.sender) { + revert InvalidMessage(); + } + if (address(uint160(uint256(message.evmReceiver))) != offer.receiver) { + revert InvalidMessage(); + } + if (address(uint160(uint256(message.evmTokenAddress))) != offer.receiver721Asset.collection) { + revert InvalidMessage(); + } + if (message.evmTokenId != offer.receiver721Asset.id) { + revert InvalidMessage(); + } + } +} diff --git a/src/Signer.sol b/src/Signer.sol index e2884ac..db61a5a 100644 --- a/src/Signer.sol +++ b/src/Signer.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "solmate/utils/ReentrancyGuard.sol"; -import "./Handler.sol"; +import "contracts/Handler.sol"; import "solady/src/utils/ECDSA.sol"; import "solady/src/utils/EIP712.sol"; +import "solmate/utils/ReentrancyGuard.sol"; error InvalidSignature(); error InvalidSigner(); diff --git a/src/TestEcho.sol b/src/TestEcho.sol index 1442c77..72b8063 100644 --- a/src/TestEcho.sol +++ b/src/TestEcho.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "./Echo.sol"; +import "contracts/Echo.sol"; // @dev Contract for development purposes only contract TestEcho is Echo { diff --git a/src/escrow/Escrow.sol b/src/escrow/Escrow.sol new file mode 100644 index 0000000..8991a5c --- /dev/null +++ b/src/escrow/Escrow.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/escrow/EscrowData.sol"; +import "contracts/escrow/EscrowHandler.sol"; +import "contracts/escrow/EscrowState.sol"; + +abstract contract Escrow is EscrowState, EscrowHandler { + function _depositForReceiver(Offer calldata offer) internal { + _transferERC721(offer.receiver721Asset.collection, offer.receiver721Asset.id, offer.receiver, address(this)); + } +} diff --git a/src/escrow/EscrowData.sol b/src/escrow/EscrowData.sol new file mode 100644 index 0000000..9ef4202 --- /dev/null +++ b/src/escrow/EscrowData.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +struct ERC721Asset { + address collection; + uint64 id; +} + +// @dev For simplicity sake, we only support 1 asset and we assume the offer is +// always created on another chain, thus theres only receiver asset +struct Offer { + address sender; + address receiver; + uint256 expiresAt; + OfferStatus status; + ERC721Asset receiver721Asset; +} + +enum OfferStatus { + Created, + Accepted, + Cancelled +} diff --git a/src/escrow/EscrowHandler.sol b/src/escrow/EscrowHandler.sol new file mode 100644 index 0000000..a41f8b8 --- /dev/null +++ b/src/escrow/EscrowHandler.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/Handler.sol"; +import "forge-std/interfaces/IERC721.sol"; + +// +abstract contract EscrowHandler is Handler, IERC721TokenReceiver { + function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) + external + pure + returns (bytes4) + { + return this.onERC721Received.selector; + } +} diff --git a/src/escrow/EscrowState.sol b/src/escrow/EscrowState.sol new file mode 100644 index 0000000..29fcb0a --- /dev/null +++ b/src/escrow/EscrowState.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/escrow/EscrowData.sol"; + +abstract contract EscrowState { + mapping(string => bool) internal _executedTrades; + mapping(string => Offer) internal _offers; +} diff --git a/src/wormhole/Message.sol b/src/wormhole/Message.sol new file mode 100644 index 0000000..6c3e899 --- /dev/null +++ b/src/wormhole/Message.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/wormhole/BytesLib.sol"; +import "contracts/wormhole/WormholeData.sol"; +import "contracts/wormhole/WormholeError.sol"; + +abstract contract Message { + using BytesLib for bytes; + + /** + * @notice Encodes the EchoMessage struct into bytes + * @param parsedMessage EchoMessage struct with arbitrary HelloWorld message + * @return encodedMessage EchoMessage encoded into bytes + */ + function _encodeMessage(EchoMessage memory parsedMessage) internal pure returns (bytes memory encodedMessage) { + // Convert message string to bytes so that we can use the .length attribute. + // The length of the arbitrary messages needs to be encoded in the message + // so that the corresponding decode function can decode the message properly. + bytes memory encodedId = abi.encodePacked(parsedMessage.id); + + // return the encoded message + encodedMessage = abi.encodePacked( + parsedMessage.payloadID, + uint16(encodedId.length), + encodedId, + parsedMessage.evmSender, + parsedMessage.evmReceiver, + parsedMessage.evmTokenAddress, + parsedMessage.solSender, + parsedMessage.solReceiver, + parsedMessage.solSenderTokenMint + ); + } + + /** + * @notice Decodes bytes into EchoMessage struct + * @dev Verifies the payloadID + * @param encodedMessage encoded arbitrary Echo message + * @return parsedMessage EchoMessage struct with Solana trade + */ + function _decodeMessage(bytes memory encodedMessage) internal pure returns (EchoMessage memory parsedMessage) { + uint256 index = 0; + + // parse and verify the payloadID + parsedMessage.payloadID = encodedMessage.toUint8(index); + if (parsedMessage.payloadID != 1) { + revert InvalidPayloadId(); + } + index += 1; + + uint256 messageLength = encodedMessage.toUint16(index); + index += 2; + + bytes memory messageBytes = encodedMessage.slice(index, messageLength); + parsedMessage.id = string(messageBytes); + index += messageLength; + + // EVM + parsedMessage.evmSender = encodedMessage.toBytes32(index); + index += 32; + parsedMessage.evmReceiver = encodedMessage.toBytes32(index); + index += 32; + parsedMessage.evmTokenAddress = encodedMessage.toBytes32(index); + index += 32; + parsedMessage.evmTokenId = encodedMessage.toUint64(index); + index += 8; + + // SOL + parsedMessage.solSender = encodedMessage.toBytes32(index); + index += 32; + parsedMessage.solReceiver = encodedMessage.toBytes32(index); + index += 32; + parsedMessage.solSenderTokenMint = encodedMessage.toBytes32(index); + index += 32; + + if (index != encodedMessage.length) { + revert InvalidMessageLength(); + } + } +} diff --git a/src/wormhole/WormholeData.sol b/src/wormhole/WormholeData.sol new file mode 100644 index 0000000..ad4beee --- /dev/null +++ b/src/wormhole/WormholeData.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +// perhaps we should have a different struct for solana chain messages? +struct EchoMessage { + // unique identifier for this message type + uint8 payloadID; + // @dev id of the offer + string id; + // @dev EVM specific message + bytes32 evmSender; + bytes32 evmReceiver; + bytes32 evmTokenAddress; + uint64 evmTokenId; + // @dev Solana specific message + bytes32 solSender; + bytes32 solReceiver; + bytes32 solSenderTokenMint; +} + +// TODO Optimize this +struct EchoMessageWithoutPayload { + // @dev id of the offer + string id; + // @dev EVM specific message + bytes32 evmSender; + bytes32 evmReceiver; + bytes32 evmTokenAddress; + uint64 evmTokenId; + // @dev Solana specific message + bytes32 solSender; + bytes32 solReceiver; + bytes32 solSenderTokenMint; +} diff --git a/src/wormhole/WormholeError.sol b/src/wormhole/WormholeError.sol new file mode 100644 index 0000000..75c0923 --- /dev/null +++ b/src/wormhole/WormholeError.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +error InvalidWormholeConfig(); +error InvalidEmitterChainId(); +error InvalidEmitterAddress(); +error InvalidEmitter(); +error FailedParsingAndVerifyingVm(); +error MessageAlreadyConsumed(); +error MessageTooLong(); +error NotEnoughWormholeFees(); +error InvalidPayloadId(); +error InvalidMessageLength(); diff --git a/src/wormhole/WormholeGovernance.sol b/src/wormhole/WormholeGovernance.sol new file mode 100644 index 0000000..9a47ed6 --- /dev/null +++ b/src/wormhole/WormholeGovernance.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/wormhole/IWormhole.sol"; +import "contracts/wormhole/Message.sol"; +import "contracts/wormhole/WormholeData.sol"; +import "contracts/wormhole/WormholeError.sol"; +import "contracts/wormhole/WormholeState.sol"; +import "solmate/auth/Owned.sol"; + +abstract contract WormholeGovernance is Owned, Message, WormholeState { + constructor(address wormhole_, uint16 _chainId, uint8 wormholeFinality_) { + if (wormhole_ == address(0)) { + revert InvalidWormholeConfig(); + } + if (_chainId == 0) { + revert InvalidWormholeConfig(); + } + if (wormholeFinality_ == 0) { + revert InvalidWormholeConfig(); + } + _state.wormhole = payable(wormhole_); + _state.chainId = _chainId; + _state.wormholeFinality = wormholeFinality_; + } + + /** + * @notice Sends an EchoMessage + * @dev batchID is set to 0 to opt out of batching in future Wormhole versions. + * Reverts if: + * - caller doesn't pass enough value to pay the Wormhole network fee + * @param message EchoMessageWithoutPayload to send + * @return messageSequence Wormhole message sequence for this contract + */ + function _sendMessage(EchoMessageWithoutPayload memory message) internal returns (uint64 messageSequence) { + IWormhole wormhole = wormholeContract(); + uint256 wormholeFee = wormhole.messageFee(); + + // TODO Add checks on the message? + + if (msg.value != wormholeFee) { + revert NotEnoughWormholeFees(); + } + + EchoMessage memory parsedMessage = EchoMessage({ + payloadID: uint8(1), + id: message.id, + evmSender: message.evmSender, + evmReceiver: message.evmReceiver, + evmTokenAddress: message.evmTokenAddress, + evmTokenId: message.evmTokenId, + solSender: message.solSender, + solReceiver: message.solReceiver, + solSenderTokenMint: message.solSenderTokenMint + }); + + bytes memory encodedMessage = _encodeMessage(parsedMessage); + + // Send the Echo message by calling publishMessage on the + // Wormhole core contract and paying the Wormhole protocol fee. + messageSequence = wormhole.publishMessage{value: wormholeFee}( + 0, // batchID + encodedMessage, + _state.wormholeFinality + ); + } + + /** + * @notice Consumes arbitrary Echo messages sent by registered emitters + * @dev The arbitrary message is verified by the Wormhole core endpoint + * `verifyVM`. + * Reverts if: + * - `encodedMessage` is not attested by the Wormhole network + * - `encodedMessage` was sent by an unregistered emitter + * - `encodedMessage` was consumed already + * @param encodedMessage verified Wormhole message containing arbitrary + * @return parsedMessage EchoMessage The parsed message from Wormhole + */ + function _receiveMessage(bytes calldata encodedMessage) internal returns (EchoMessage memory parsedMessage) { + // call the Wormhole core contract to parse and verify the encodedMessage + (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = + wormholeContract().parseAndVerifyVM(encodedMessage); + + if (!valid) { + // TODO Add reason? + revert FailedParsingAndVerifyingVm(); + } + + if (!_verifyEmitter(wormholeMessage)) { + revert InvalidEmitter(); + } + + parsedMessage = _decodeMessage(wormholeMessage.payload); + + if (isMessageConsumed(wormholeMessage.hash)) { + revert MessageAlreadyConsumed(); + } + _consumeMessage(wormholeMessage.hash); + } +} diff --git a/src/wormhole/WormholeState.sol b/src/wormhole/WormholeState.sol new file mode 100644 index 0000000..927afc1 --- /dev/null +++ b/src/wormhole/WormholeState.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/wormhole/IWormhole.sol"; +import "contracts/wormhole/WormholeError.sol"; +import "solmate/auth/Owned.sol"; + +struct State { + // address of the Wormhole contract on this chain + address wormhole; + // Need to store the chain ID as it might differ from the real id + // I.e. Ethereum is chainId = 2 for Wormhole because Solana is chainId = 1 + uint16 chainId; + /** + * The number of block confirmations needed before the wormhole network + * will attest a message. + */ + uint8 wormholeFinality; + /** + * Wormhole chain ID to known emitter address mapping. xDapps using + * Wormhole should register all deployed contracts on each chain to + * verify that messages being consumed are from trusted contracts. + */ + mapping(uint16 => bytes32) registeredEmitters; + // verified message hash to boolean + mapping(bytes32 => bool) consumedMessages; +} + +abstract contract WormholeState is Owned { + State internal _state; + + function isMessageConsumed(bytes32 hash) public view returns (bool) { + return _state.consumedMessages[hash]; + } + + function wormholeContract() public view returns (IWormhole) { + return IWormhole(_state.wormhole); + } + + function _setEmitter(uint16 chainId, bytes32 emitter) internal { + _state.registeredEmitters[chainId] = emitter; + } + + function _consumeMessage(bytes32 hash) internal { + _state.consumedMessages[hash] = true; + } + + /** + * @notice Registers foreign emitters (Echo contracts) with this contract + * @dev Only the deployer (owner) can invoke this method + * @param emitterChainId Wormhole chainId of the contract being registered + * See https://book.wormhole.com/reference/contracts.html for more information. + * @param emitterAddress 32-byte address of the contract being registered. For EVM + * contracts the first 12 bytes should be zeros. + */ + function registerEmitter(uint16 emitterChainId, bytes32 emitterAddress) external onlyOwner { + // sanity check the emitterChainId and emitterAddress input values + if (emitterChainId == _state.chainId) { + revert InvalidEmitterChainId(); + } + if (emitterAddress == bytes32(0)) { + revert InvalidEmitterAddress(); + } + + _setEmitter(emitterChainId, emitterAddress); + } + + function _verifyEmitter(IWormhole.VM memory vm) internal view returns (bool) { + return _state.registeredEmitters[vm.emitterChainId] == vm.emitterAddress; + } +} From f7c595f2c5490943d45d1535d5d39829c6c48d23 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:50:17 -0400 Subject: [PATCH 04/28] WIP Added bridge test --- package.json | 1 + src/EchoCrossChain.sol | 4 +- src/wormhole/WormholeGovernance.sol | 4 +- src/wormhole/WormholeState.sol | 12 +- test/TestBridge.t.sol | 146 +++++++++ test/utils/MockWormhole.sol | 283 +++++++++++++++++ test/utils/WormholeSimulator.sol | 467 ++++++++++++++++++++++++++++ testing.env | 42 +++ 8 files changed, 951 insertions(+), 8 deletions(-) create mode 100644 test/TestBridge.t.sol create mode 100644 test/utils/MockWormhole.sol create mode 100644 test/utils/WormholeSimulator.sol create mode 100644 testing.env diff --git a/package.json b/package.json index 411de9c..ff4a33e 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "pretty": "forge fmt", "build": "forge build", "test": "forge test -vvv", + "test:bridge": "forge test --fork-url https://api.avax.network/ext/bc/C/rpc -vvv", "test:gas-report": "forge test --gas-report", "snapshot": "forge snapshot; cat .gas-snapshot", "coverage": "forge coverage --report lcov", diff --git a/src/EchoCrossChain.sol b/src/EchoCrossChain.sol index dd19f94..c94ec7b 100644 --- a/src/EchoCrossChain.sol +++ b/src/EchoCrossChain.sol @@ -25,13 +25,13 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover {} // @dev This function assumes that the offer was created on another chain. - function acceptOffer(string calldata offerId, Offer calldata offer, bytes calldata encodedMessage) + function acceptOffer(string calldata offerId, Offer calldata offer, bytes memory encodedMessage) external payable nonReentrant notPaused { - if (_offers[offerId].sender == address(0)) { + if (_offers[offerId].sender != address(0)) { revert OfferAlreadyExist(); } // @dev diff --git a/src/wormhole/WormholeGovernance.sol b/src/wormhole/WormholeGovernance.sol index 9a47ed6..12859f6 100644 --- a/src/wormhole/WormholeGovernance.sol +++ b/src/wormhole/WormholeGovernance.sol @@ -32,7 +32,7 @@ abstract contract WormholeGovernance is Owned, Message, WormholeState { * @param message EchoMessageWithoutPayload to send * @return messageSequence Wormhole message sequence for this contract */ - function _sendMessage(EchoMessageWithoutPayload memory message) internal returns (uint64 messageSequence) { + function _sendMessage(EchoMessageWithoutPayload memory message) public payable returns (uint64 messageSequence) { IWormhole wormhole = wormholeContract(); uint256 wormholeFee = wormhole.messageFee(); @@ -76,7 +76,7 @@ abstract contract WormholeGovernance is Owned, Message, WormholeState { * @param encodedMessage verified Wormhole message containing arbitrary * @return parsedMessage EchoMessage The parsed message from Wormhole */ - function _receiveMessage(bytes calldata encodedMessage) internal returns (EchoMessage memory parsedMessage) { + function _receiveMessage(bytes memory encodedMessage) public returns (EchoMessage memory parsedMessage) { // call the Wormhole core contract to parse and verify the encodedMessage (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = wormholeContract().parseAndVerifyVM(encodedMessage); diff --git a/src/wormhole/WormholeState.sol b/src/wormhole/WormholeState.sol index 927afc1..0571ab5 100644 --- a/src/wormhole/WormholeState.sol +++ b/src/wormhole/WormholeState.sol @@ -37,14 +37,18 @@ abstract contract WormholeState is Owned { return IWormhole(_state.wormhole); } - function _setEmitter(uint16 chainId, bytes32 emitter) internal { - _state.registeredEmitters[chainId] = emitter; - } + // function _setEmitter(uint16 chainId, bytes32 emitter) internal { + // _state.registeredEmitters[chainId] = emitter; + // } function _consumeMessage(bytes32 hash) internal { _state.consumedMessages[hash] = true; } + function chainId() public view returns (uint16) { + return _state.chainId; + } + /** * @notice Registers foreign emitters (Echo contracts) with this contract * @dev Only the deployer (owner) can invoke this method @@ -62,7 +66,7 @@ abstract contract WormholeState is Owned { revert InvalidEmitterAddress(); } - _setEmitter(emitterChainId, emitterAddress); + _state.registeredEmitters[emitterChainId] = emitterAddress; } function _verifyEmitter(IWormhole.VM memory vm) internal view returns (bool) { diff --git a/test/TestBridge.t.sol b/test/TestBridge.t.sol new file mode 100644 index 0000000..616e1a9 --- /dev/null +++ b/test/TestBridge.t.sol @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: Apache 2 +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; +import "./mock/Mocked721.t.sol"; +import "./utils/WormholeSimulator.sol"; +import "contracts/EchoCrossChain.sol"; +import "contracts/escrow/EscrowData.sol"; +import "contracts/wormhole/WormholeData.sol"; + +/** + * @title A Test Suite for the EVM EchoCrossChain Contracts + */ +contract TestBridge is Test { + // guardian private key for simulated signing of Wormhole messages + uint256 guardianSigner; + + // contract instances + IWormhole wormhole; + WormholeSimulator wormholeSimulator; + EchoCrossChain echoSource; + EchoCrossChain echoTarget; + + address public constant owner = address(1313); + address public constant sender = address(1337); + address public constant receiver = address(1339); + + Mocked721 public apes; + Mocked721 public birds; + + address public apeAddress; + uint256 public ape1Id; + address public birdAddress; + uint256 public bird1Id; + + /** + * @notice Sets up the wormholeSimulator contracts and deploys HelloWorld + * contracts before each test is executed. + */ + function setUp() public { + // Fund accounts + vm.deal(sender, 100 ether); + vm.deal(receiver, 100 ether); + + apes = new Mocked721("Apes", "APE"); + birds = new Mocked721("Birds", "BIRD"); + + apes.safeMint(sender, 1); + + birds.safeMint(receiver, 1); + + // verify that we're using the correct fork (AVAX mainnet in this case) + require(block.chainid == vm.envUint("TESTING_AVAX_FORK_CHAINID"), "wrong evm"); + + // this will be used to sign Wormhole messages + guardianSigner = uint256(vm.envBytes32("TESTING_DEVNET_GUARDIAN")); + + // we may need to interact with Wormhole throughout the test + wormhole = IWormhole(vm.envAddress("TESTING_AVAX_WORMHOLE_ADDRESS")); + + // set up Wormhole using Wormhole existing on AVAX mainnet + wormholeSimulator = new SigningWormholeSimulator(wormhole, guardianSigner); + + // verify Wormhole state from fork + require(wormhole.chainId() == uint16(vm.envUint("TESTING_AVAX_WORMHOLE_CHAINID")), "wrong chainId"); + require(wormhole.messageFee() == vm.envUint("TESTING_AVAX_WORMHOLE_MESSAGE_FEE"), "wrong messageFee"); + require( + wormhole.getCurrentGuardianSetIndex() == uint32(vm.envUint("TESTING_AVAX_WORMHOLE_GUARDIAN_SET_INDEX")), + "wrong guardian set index" + ); + + echoSource = new EchoCrossChain(address(owner), address(wormhole), wormhole.chainId(), uint8(1)); + echoTarget = new EchoCrossChain(address(owner), address(wormhole), uint8(2), uint8(1)); + + // confirm that the source and target contract addresses are different + assertTrue(address(echoSource) != address(echoTarget)); + } + + function testAcceptTrade() public { + // start listening to events + vm.recordLogs(); + + bytes32 evmSender = bytes32(uint256(uint160(sender)) << 96); + bytes32 evmReceiver = bytes32(uint256(uint160(receiver)) << 96); + bytes32 evmTokenAddress = bytes32(uint256(uint160(address(birds))) << 96); + uint64 evmTokenId = uint64(1); + bytes32 solSender = bytes32(0); + bytes32 solReceiver = bytes32(0); + bytes32 solSenderTokenMint = bytes32(0); + + EchoMessageWithoutPayload memory message = EchoMessageWithoutPayload({ + id: "test", + evmSender: evmSender, + evmReceiver: evmReceiver, + evmTokenAddress: evmTokenAddress, + evmTokenId: evmTokenId, + solSender: solSender, + solReceiver: solReceiver, + solSenderTokenMint: solSenderTokenMint + }); + echoTarget._sendMessage(message); + + // record the emitted wormhole message + Vm.Log[] memory entries = vm.getRecordedLogs(); + + // simulate signing the Wormhole message + // NOTE: in the wormhole-sdk, signed Wormhole messages are referred to as signed VAAs + bytes memory encodedMessage = + wormholeSimulator.fetchSignedMessageFromLogs(entries[0], echoTarget.chainId(), address(echoTarget)); + + vm.startPrank(owner); + // register the emitter on the source contract + echoSource.registerEmitter(echoTarget.chainId(), bytes32(uint256(uint160(address(echoTarget))))); + vm.stopPrank(); + + vm.startPrank(receiver); + echoSource.acceptOffer( + "test", + Offer({ + sender: sender, + receiver: receiver, + expiresAt: block.timestamp + (60 * 60 * 6), + status: OfferStatus.Created, + receiver721Asset: ERC721Asset({collection: address(birds), id: evmTokenId}) + }), + encodedMessage + ); + + // Parse the encodedMessage to retrieve the hash. This is a safe operation + // since the source HelloWorld contract already verfied the message in the + // previous call. + IWormhole.VM memory parsedMessage = wormhole.parseVM(encodedMessage); + + // Verify that the message was consumed and the payload was saved + // in the contract state. + bool messageWasConsumed = echoSource.isMessageConsumed(parsedMessage.hash); + + assertTrue(messageWasConsumed); + + // Confirm that message replay protection works by trying to call receiveMessage + // with the same Wormhole message again. + vm.expectRevert("message already consumed"); + echoSource._receiveMessage(encodedMessage); + } +} diff --git a/test/utils/MockWormhole.sol b/test/utils/MockWormhole.sol new file mode 100644 index 0000000..74a90eb --- /dev/null +++ b/test/utils/MockWormhole.sol @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: Apache 2 + +pragma solidity ^0.8.18; + +import "contracts/wormhole/IWormhole.sol"; +import "contracts/wormhole/BytesLib.sol"; + +contract MockWormhole is IWormhole { + using BytesLib for bytes; + + uint256 private constant VM_VERSION_SIZE = 1; + uint256 private constant VM_GUARDIAN_SET_SIZE = 4; + uint256 private constant VM_SIGNATURE_COUNT_SIZE = 1; + uint256 private constant VM_TIMESTAMP_SIZE = 4; + uint256 private constant VM_NONCE_SIZE = 4; + uint256 private constant VM_EMITTER_CHAIN_ID_SIZE = 2; + uint256 private constant VM_EMITTER_ADDRESS_SIZE = 32; + uint256 private constant VM_SEQUENCE_SIZE = 8; + uint256 private constant VM_CONSISTENCY_LEVEL_SIZE = 1; + uint256 private constant VM_SIZE_MINIMUM = VM_VERSION_SIZE + VM_GUARDIAN_SET_SIZE + VM_SIGNATURE_COUNT_SIZE + + VM_TIMESTAMP_SIZE + VM_NONCE_SIZE + VM_EMITTER_CHAIN_ID_SIZE + VM_EMITTER_ADDRESS_SIZE + VM_SEQUENCE_SIZE + + VM_CONSISTENCY_LEVEL_SIZE; + + uint256 private constant SIGNATURE_GUARDIAN_INDEX_SIZE = 1; + uint256 private constant SIGNATURE_R_SIZE = 32; + uint256 private constant SIGNATURE_S_SIZE = 32; + uint256 private constant SIGNATURE_V_SIZE = 1; + uint256 private constant SIGNATURE_SIZE_TOTAL = + SIGNATURE_GUARDIAN_INDEX_SIZE + SIGNATURE_R_SIZE + SIGNATURE_S_SIZE + SIGNATURE_V_SIZE; + + mapping(address => uint64) public sequences; + // Dictionary of VMs that must be mocked as invalid. + mapping(bytes32 => bool) public invalidVMs; + + uint256 currentMsgFee; + uint16 immutable wormholeChainId; + uint256 immutable boundEvmChainId; + + constructor(uint16 initChainId, uint256 initEvmChainId) { + wormholeChainId = initChainId; + boundEvmChainId = initEvmChainId; + } + + function invalidateVM(bytes calldata encodedVm) external { + VM memory vm = _parseVM(encodedVm); + invalidVMs[vm.hash] = true; + } + + function publishMessage(uint32 nonce, bytes memory payload, uint8 consistencyLevel) + external + payable + returns (uint64 sequence) + { + require(msg.value == currentMsgFee, "invalid fee"); + sequence = sequences[msg.sender]++; + emit LogMessagePublished(msg.sender, sequence, nonce, payload, consistencyLevel); + } + + function parseVM(bytes calldata encodedVm) external pure returns (VM memory vm) { + vm = _parseVM(encodedVm); + } + + function parseAndVerifyVM(bytes calldata encodedVm) + external + view + returns (VM memory vm, bool valid, string memory reason) + { + vm = _parseVM(encodedVm); + //behold the rigorous checking! + valid = !invalidVMs[vm.hash]; + reason = ""; + } + + function _parseVM(bytes calldata encodedVm) internal pure returns (VM memory vm) { + require(encodedVm.length >= VM_SIZE_MINIMUM, "vm too small"); + + bytes memory body; + + uint256 offset = 0; + vm.version = encodedVm.toUint8(offset); + offset += 1; + + vm.guardianSetIndex = encodedVm.toUint32(offset); + offset += 4; + + (vm.signatures, offset) = parseSignatures(encodedVm, offset); + + body = encodedVm[offset:]; + vm.timestamp = encodedVm.toUint32(offset); + offset += 4; + + vm.nonce = encodedVm.toUint32(offset); + offset += 4; + + vm.emitterChainId = encodedVm.toUint16(offset); + offset += 2; + + vm.emitterAddress = encodedVm.toBytes32(offset); + offset += 32; + + vm.sequence = encodedVm.toUint64(offset); + offset += 8; + + vm.consistencyLevel = encodedVm.toUint8(offset); + offset += 1; + + vm.payload = encodedVm[offset:]; + vm.hash = keccak256(abi.encodePacked(keccak256(body))); + } + + function parseSignatures(bytes calldata encodedVm, uint256 offset) + internal + pure + returns (Signature[] memory signatures, uint256 offsetAfterParse) + { + uint256 sigCount = uint256(encodedVm.toUint8(offset)); + offset += 1; + + require(encodedVm.length >= (VM_SIZE_MINIMUM + sigCount * SIGNATURE_SIZE_TOTAL), "vm too small"); + + signatures = new Signature[](sigCount); + for (uint256 i = 0; i < sigCount; ++i) { + uint8 guardianIndex = encodedVm.toUint8(offset); + offset += 1; + + bytes32 r = encodedVm.toBytes32(offset); + offset += 32; + + bytes32 s = encodedVm.toBytes32(offset); + offset += 32; + + uint8 v = encodedVm.toUint8(offset); + offset += 1; + + signatures[i] = Signature({ + r: r, + s: s, + // The hardcoded 27 comes from the base offset for public key recovery ids, public key type and network + // used in ECDSA signatures for bitcoin and ethereum. + // See https://bitcoin.stackexchange.com/a/5089 + v: v + 27, + guardianIndex: guardianIndex + }); + } + + return (signatures, offset); + } + + function initialize() external {} + + function quorum(uint256 /*numGuardians*/ ) external pure returns (uint256 /*numSignaturesRequiredForQuorum*/ ) { + return 1; + } + + /** + * General state and chain observers + */ + function chainId() external view returns (uint16) { + return wormholeChainId; + } + + function evmChainId() external view returns (uint256) { + return boundEvmChainId; + } + + function getCurrentGuardianSetIndex() external pure returns (uint32) { + return 0; + } + + function getGuardianSet(uint32 /*index*/ ) external pure returns (GuardianSet memory) { + revert("unsupported getGuardianSet in wormhole mock"); + } + + function getGuardianSetExpiry() external pure returns (uint32) { + return 0; + } + + function governanceActionIsConsumed(bytes32 /*hash*/ ) external pure returns (bool) { + return false; + } + + function isInitialized(address /*impl*/ ) external pure returns (bool) { + return true; + } + + function isFork() external pure returns (bool) { + return false; + } + + function governanceChainId() external pure returns (uint16) { + return 1; + } + + function governanceContract() external pure returns (bytes32) { + return bytes32(0x0000000000000000000000000000000000000000000000000000000000000004); + } + + function messageFee() external view returns (uint256) { + return currentMsgFee; + } + + function nextSequence(address emitter) external view returns (uint64) { + return sequences[emitter]; + } + + function verifyVM(VM memory /*vm*/ ) external pure returns (bool, /*valid*/ string memory /*reason*/ ) { + revert("unsupported verifyVM in wormhole mock"); + } + + function verifySignatures( + bytes32, + /*hash*/ + Signature[] memory, + /*signatures*/ + GuardianSet memory /*guardianSet*/ + ) external pure returns (bool, /*valid*/ string memory /*reason*/ ) { + revert("unsupported verifySignatures in wormhole mock"); + } + + function parseContractUpgrade(bytes memory /*encodedUpgrade*/ ) + external + pure + returns (ContractUpgrade memory /*cu*/ ) + { + revert("unsupported parseContractUpgrade in wormhole mock"); + } + + function parseGuardianSetUpgrade(bytes memory /*encodedUpgrade*/ ) + external + pure + returns (GuardianSetUpgrade memory /*gsu*/ ) + { + revert("unsupported parseGuardianSetUpgrade in wormhole mock"); + } + + function parseSetMessageFee(bytes memory /*encodedSetMessageFee*/ ) + external + pure + returns (SetMessageFee memory /*smf*/ ) + { + revert("unsupported parseSetMessageFee in wormhole mock"); + } + + function parseTransferFees(bytes memory /*encodedTransferFees*/ ) + external + pure + returns (TransferFees memory /*tf*/ ) + { + revert("unsupported parseTransferFees in wormhole mock"); + } + + function parseRecoverChainId(bytes memory /*encodedRecoverChainId*/ ) + external + pure + returns (RecoverChainId memory /*rci*/ ) + { + revert("unsupported parseRecoverChainId in wormhole mock"); + } + + function submitContractUpgrade(bytes memory /*_vm*/ ) external pure { + revert("unsupported submitContractUpgrade in wormhole mock"); + } + + function submitSetMessageFee(bytes memory /*_vm*/ ) external pure { + revert("unsupported submitSetMessageFee in wormhole mock"); + } + + function setMessageFee(uint256 newFee) external { + currentMsgFee = newFee; + } + + function submitNewGuardianSet(bytes memory /*_vm*/ ) external pure { + revert("unsupported submitNewGuardianSet in wormhole mock"); + } + + function submitTransferFees(bytes memory /*_vm*/ ) external pure { + revert("unsupported submitTransferFees in wormhole mock"); + } + + function submitRecoverChainId(bytes memory /*_vm*/ ) external pure { + revert("unsupported submitRecoverChainId in wormhole mock"); + } +} diff --git a/test/utils/WormholeSimulator.sol b/test/utils/WormholeSimulator.sol new file mode 100644 index 0000000..692209b --- /dev/null +++ b/test/utils/WormholeSimulator.sol @@ -0,0 +1,467 @@ +// SPDX-License-Identifier: Apache 2 +pragma solidity ^0.8.18; + +import "forge-std/Vm.sol"; +import "forge-std/console.sol"; + +import "contracts/wormhole/IWormhole.sol"; +import "./MockWormhole.sol"; +import "contracts/wormhole/BytesLib.sol"; + +/** + * @notice These are the common parts for the signing and the non signing wormhole simulators. + * @dev This contract is meant to be used when testing against a mainnet fork. + */ +abstract contract WormholeSimulator { + using BytesLib for bytes; + + function doubleKeccak256(bytes memory body) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(keccak256(body))); + } + + function parseVMFromLogs(Vm.Log memory log) public pure returns (IWormhole.VM memory vm_) { + uint256 index = 0; + + // emitterAddress + vm_.emitterAddress = bytes32(log.topics[1]); + + // sequence + vm_.sequence = log.data.toUint64(index + 32 - 8); + index += 32; + + // nonce + vm_.nonce = log.data.toUint32(index + 32 - 4); + index += 32; + + // skip random bytes + index += 32; + + // consistency level + vm_.consistencyLevel = log.data.toUint8(index + 32 - 1); + index += 32; + + // length of payload + uint256 payloadLen = log.data.toUint256(index); + index += 32; + + vm_.payload = log.data.slice(index, payloadLen); + index += payloadLen; + + // trailing bytes (due to 32 byte slot overlap) + index += log.data.length - index; + + require(index == log.data.length, "failed to parse wormhole message"); + } + + /** + * @notice Finds published Wormhole events in forge logs + * @param logs The forge Vm.log captured when recording events during test execution + */ + function fetchWormholeMessageFromLog(Vm.Log[] memory logs) public pure returns (Vm.Log[] memory) { + uint256 count = 0; + for (uint256 i = 0; i < logs.length; i++) { + if (logs[i].topics[0] == keccak256("LogMessagePublished(address,uint64,uint32,bytes,uint8)")) { + count += 1; + } + } + + // create log array to save published messages + Vm.Log[] memory published = new Vm.Log[](count); + + uint256 publishedIndex = 0; + for (uint256 i = 0; i < logs.length; i++) { + if (logs[i].topics[0] == keccak256("LogMessagePublished(address,uint64,uint32,bytes,uint8)")) { + published[publishedIndex] = logs[i]; + publishedIndex += 1; + } + } + + return published; + } + + /** + * @notice Encodes Wormhole message body into bytes + * @param vm_ Wormhole VM struct + * @return encodedObservation Wormhole message body encoded into bytes + */ + function encodeObservation(IWormhole.VM memory vm_) public pure returns (bytes memory encodedObservation) { + encodedObservation = abi.encodePacked( + vm_.timestamp, + vm_.nonce, + vm_.emitterChainId, + vm_.emitterAddress, + vm_.sequence, + vm_.consistencyLevel, + vm_.payload + ); + } + + /** + * @notice Formats and signs a simulated Wormhole message using the emitted log from calling `publishMessage` + * @param log The forge Vm.log captured when recording events during test execution + * @return signedMessage Formatted and signed Wormhole message + */ + function fetchSignedMessageFromLogs(Vm.Log memory log, uint16 emitterChainId, address emitterAddress) + public + returns (bytes memory signedMessage) + { + // Parse wormhole message from ethereum logs + IWormhole.VM memory vm_ = parseVMFromLogs(log); + + // Set empty body values before computing the hash + vm_.version = uint8(1); + vm_.timestamp = uint32(block.timestamp); + vm_.emitterChainId = emitterChainId; + vm_.emitterAddress = bytes32(uint256(uint160(emitterAddress))); + + return encodeAndSignMessage(vm_); + } + + /** + * Functions that must be implemented by concrete wormhole simulators. + */ + + /** + * @notice Sets the message fee for a wormhole message. + */ + function setMessageFee(uint256 newFee) public virtual; + + /** + * @notice Invalidates a VM. It must be executed before it is parsed and verified by the Wormhole instance to work. + */ + function invalidateVM(bytes memory message) public virtual; + + /** + * @notice Formats and signs a simulated Wormhole batch VAA given an array of Wormhole log entries + * @param logs The forge Vm.log entries captured when recording events during test execution + * @param nonce The nonce of the messages to be accumulated into the batch VAA + * @return signedMessage Formatted and signed Wormhole message + */ + function fetchSignedBatchVAAFromLogs( + Vm.Log[] memory logs, + uint32 nonce, + uint16 emitterChainId, + address emitterAddress + ) public virtual returns (bytes memory signedMessage); + + /** + * @notice Signs and preformatted simulated Wormhole message + * @param vm_ The preformatted Wormhole message + * @return signedMessage Formatted and signed Wormhole message + */ + function encodeAndSignMessage(IWormhole.VM memory vm_) public virtual returns (bytes memory signedMessage); +} + +/** + * @title A Wormhole Guardian Simulator + * @notice This contract simulates signing Wormhole messages emitted in a forge test. + * This particular version doesn't sign any message but just exists to keep a standard interface for tests. + * @dev This contract is meant to be used with the MockWormhole contract that validates any VM as long + * as its hash wasn't banned. + */ +contract FakeWormholeSimulator is WormholeSimulator { + // Allow access to Wormhole + MockWormhole public wormhole; + + /** + * @param initWormhole address of the Wormhole core contract for the mainnet chain being forked + */ + constructor(MockWormhole initWormhole) { + wormhole = initWormhole; + } + + function setMessageFee(uint256 newFee) public override { + wormhole.setMessageFee(newFee); + } + + function invalidateVM(bytes memory message) public override { + wormhole.invalidateVM(message); + } + + /** + * @notice Formats and signs a simulated Wormhole batch VAA given an array of Wormhole log entries + * @param logs The forge Vm.log entries captured when recording events during test execution + * @param nonce The nonce of the messages to be accumulated into the batch VAA + * @return signedMessage Formatted and signed Wormhole message + */ + function fetchSignedBatchVAAFromLogs( + Vm.Log[] memory logs, + uint32 nonce, + uint16 emitterChainId, + address emitterAddress + ) public view override returns (bytes memory signedMessage) { + uint8 numObservations = 0; + IWormhole.VM[] memory vm_ = new IWormhole.VM[](logs.length); + + for (uint256 i = 0; i < logs.length; i++) { + vm_[i] = parseVMFromLogs(logs[i]); + vm_[i].timestamp = uint32(block.timestamp); + vm_[i].emitterChainId = emitterChainId; + vm_[i].emitterAddress = bytes32(uint256(uint160(emitterAddress))); + if (vm_[i].nonce == nonce) { + numObservations += 1; + } + } + + bytes memory packedObservations; + bytes32[] memory hashes = new bytes32[](numObservations); + + uint8 counter = 0; + for (uint256 i = 0; i < logs.length; i++) { + if (vm_[i].nonce == nonce) { + bytes memory observation = abi.encodePacked( + vm_[i].timestamp, + vm_[i].nonce, + vm_[i].emitterChainId, + vm_[i].emitterAddress, + vm_[i].sequence, + vm_[i].consistencyLevel, + vm_[i].payload + ); + hashes[counter] = doubleKeccak256(observation); + packedObservations = + abi.encodePacked(packedObservations, uint8(counter), uint32(observation.length), observation); + counter++; + } + } + + signedMessage = abi.encodePacked( + // vm version + uint8(2), + wormhole.getCurrentGuardianSetIndex(), + // length of signature array + uint8(1), + // guardian index + uint8(0), + // r sig argument + bytes32(uint256(0)), + // s sig argument + bytes32(uint256(0)), + // v sig argument (encodes public key recovery id, public key type and network of the signature) + uint8(0), + numObservations, + hashes, + numObservations, + packedObservations + ); + } + + /** + * @notice Signs and preformatted simulated Wormhole message + * @param vm_ The preformatted Wormhole message + * @return signedMessage Formatted and signed Wormhole message + */ + function encodeAndSignMessage(IWormhole.VM memory vm_) public view override returns (bytes memory signedMessage) { + // Compute the hash of the body + bytes memory body = encodeObservation(vm_); + vm_.hash = doubleKeccak256(body); + + signedMessage = abi.encodePacked( + vm_.version, + wormhole.getCurrentGuardianSetIndex(), + // length of signature array + uint8(1), + // guardian index + uint8(0), + // r sig argument + bytes32(uint256(0)), + // s sig argument + bytes32(uint256(0)), + // v sig argument (encodes public key recovery id, public key type and network of the signature) + uint8(0), + body + ); + } +} + +/** + * @title A Wormhole Guardian Simulator + * @notice This contract simulates signing Wormhole messages emitted in a forge test. + * It overrides the Wormhole guardian set to allow for signing messages with a single + * private key on any EVM where Wormhole core contracts are deployed. + * @dev This contract is meant to be used when testing against a mainnet fork. + */ +contract SigningWormholeSimulator is WormholeSimulator { + // Taken from forge-std/Script.sol + address private constant VM_ADDRESS = address(bytes20(uint160(uint256(keccak256("hevm cheat code"))))); + Vm public constant vm = Vm(VM_ADDRESS); + + // Allow access to Wormhole + IWormhole public wormhole; + + // Save the guardian PK to sign messages with + uint256 private devnetGuardianPK; + + /** + * @param wormhole_ address of the Wormhole core contract for the mainnet chain being forked + * @param devnetGuardian private key of the devnet Guardian + */ + constructor(IWormhole wormhole_, uint256 devnetGuardian) { + wormhole = wormhole_; + devnetGuardianPK = devnetGuardian; + overrideToDevnetGuardian(vm.addr(devnetGuardian)); + } + + function overrideToDevnetGuardian(address devnetGuardian) internal { + { + // Get slot for Guardian Set at the current index + uint32 guardianSetIndex = wormhole.getCurrentGuardianSetIndex(); + bytes32 guardianSetSlot = keccak256(abi.encode(guardianSetIndex, 2)); + + // Overwrite all but first guardian set to zero address. This isn't + // necessary, but just in case we inadvertently access these slots + // for any reason. + uint256 numGuardians = uint256(vm.load(address(wormhole), guardianSetSlot)); + for (uint256 i = 1; i < numGuardians;) { + vm.store( + address(wormhole), bytes32(uint256(keccak256(abi.encodePacked(guardianSetSlot))) + i), bytes32(0) + ); + unchecked { + i += 1; + } + } + + // Now overwrite the first guardian key with the devnet key specified + // in the function argument. + vm.store( + address(wormhole), + bytes32(uint256(keccak256(abi.encodePacked(guardianSetSlot))) + 0), // just explicit w/ index 0 + bytes32(uint256(uint160(devnetGuardian))) + ); + + // Change the length to 1 guardian + vm.store( + address(wormhole), + guardianSetSlot, + bytes32(uint256(1)) // length == 1 + ); + + // Confirm guardian set override + address[] memory guardians = wormhole.getGuardianSet(guardianSetIndex).keys; + require(guardians.length == 1, "guardians.length != 1"); + require(guardians[0] == devnetGuardian, "incorrect guardian set override"); + } + } + + function setMessageFee(uint256 newFee) public override { + bytes32 coreModule = 0x00000000000000000000000000000000000000000000000000000000436f7265; + bytes memory message = abi.encodePacked(coreModule, uint8(3), uint16(wormhole.chainId()), newFee); + IWormhole.VM memory preSignedMessage = IWormhole.VM({ + version: 1, + timestamp: uint32(block.timestamp), + nonce: 0, + emitterChainId: wormhole.governanceChainId(), + emitterAddress: wormhole.governanceContract(), + sequence: 0, + consistencyLevel: 200, + payload: message, + guardianSetIndex: 0, + signatures: new IWormhole.Signature[](0), + hash: bytes32("") + }); + + bytes memory signed = encodeAndSignMessage(preSignedMessage); + wormhole.submitSetMessageFee(signed); + } + + function invalidateVM(bytes memory message) public pure override { + // Don't do anything. Signatures are easily invalidated modifying the payload. + // If it becomes necessary to prevent producing a good signature for this message, that can be done here. + } + + /** + * @notice Formats and signs a simulated Wormhole batch VAA given an array of Wormhole log entries + * @param logs The forge Vm.log entries captured when recording events during test execution + * @param nonce The nonce of the messages to be accumulated into the batch VAA + * @return signedMessage Formatted and signed Wormhole message + */ + function fetchSignedBatchVAAFromLogs( + Vm.Log[] memory logs, + uint32 nonce, + uint16 emitterChainId, + address emitterAddress + ) public view override returns (bytes memory signedMessage) { + uint8 numObservations = 0; + IWormhole.VM[] memory vm_ = new IWormhole.VM[](logs.length); + + for (uint256 i = 0; i < logs.length; i++) { + vm_[i] = parseVMFromLogs(logs[i]); + vm_[i].timestamp = uint32(block.timestamp); + vm_[i].emitterChainId = emitterChainId; + vm_[i].emitterAddress = bytes32(uint256(uint160(emitterAddress))); + if (vm_[i].nonce == nonce) { + numObservations += 1; + } + } + + bytes memory packedObservations; + bytes32[] memory hashes = new bytes32[](numObservations); + + uint8 counter = 0; + for (uint256 i = 0; i < logs.length; i++) { + if (vm_[i].nonce == nonce) { + bytes memory observation = abi.encodePacked( + vm_[i].timestamp, + vm_[i].nonce, + vm_[i].emitterChainId, + vm_[i].emitterAddress, + vm_[i].sequence, + vm_[i].consistencyLevel, + vm_[i].payload + ); + hashes[counter] = doubleKeccak256(observation); + packedObservations = + abi.encodePacked(packedObservations, uint8(counter), uint32(observation.length), observation); + counter++; + } + } + + bytes32 batchHash = doubleKeccak256(abi.encodePacked(uint8(2), keccak256(abi.encodePacked(hashes)))); + + IWormhole.Signature[] memory sigs = new IWormhole.Signature[](1); + (sigs[0].v, sigs[0].r, sigs[0].s) = vm.sign(devnetGuardianPK, batchHash); + + sigs[0].guardianIndex = 0; + + signedMessage = abi.encodePacked( + uint8(2), + wormhole.getCurrentGuardianSetIndex(), + uint8(1), + sigs[0].guardianIndex, + sigs[0].r, + sigs[0].s, + uint8(sigs[0].v - 27), + numObservations, + hashes, + numObservations, + packedObservations + ); + } + + /** + * @notice Signs and preformatted simulated Wormhole message + * @param vm_ The preformatted Wormhole message + * @return signedMessage Formatted and signed Wormhole message + */ + function encodeAndSignMessage(IWormhole.VM memory vm_) public view override returns (bytes memory signedMessage) { + // Compute the hash of the body + bytes memory body = encodeObservation(vm_); + vm_.hash = doubleKeccak256(body); + + // Sign the hash with the devnet guardian private key + IWormhole.Signature[] memory sigs = new IWormhole.Signature[](1); + (sigs[0].v, sigs[0].r, sigs[0].s) = vm.sign(devnetGuardianPK, vm_.hash); + sigs[0].guardianIndex = 0; + + signedMessage = abi.encodePacked( + vm_.version, + wormhole.getCurrentGuardianSetIndex(), + uint8(sigs.length), + sigs[0].guardianIndex, + sigs[0].r, + sigs[0].s, + sigs[0].v - 27, + body + ); + } +} diff --git a/testing.env b/testing.env new file mode 100644 index 0000000..e15a831 --- /dev/null +++ b/testing.env @@ -0,0 +1,42 @@ +############################################################################### +# +# Private key of devnet (Tilt) guardian +# +############################################################################### +export TESTING_DEVNET_GUARDIAN=cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0 + +############################################################################### +# +# Private keys of anvil wallets +# +############################################################################### +export WALLET_PRIVATE_KEY=4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d +export WALLET_PRIVATE_KEY_TWO=6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1 + +############################################################################### +# +# Avalanche Mainnet +# +############################################################################### +export TESTING_AVAX_FORK_RPC=https://api.avax.network/ext/bc/C/rpc +export TESTING_AVAX_FORK_CHAINID=43114 +export TESTING_AVAX_WORMHOLE_ADDRESS=0x54a8e5f9c4CbA08F9943965859F6c34eAF03E26c +export TESTING_AVAX_BRIDGE_ADDRESS=0x0e082F06FF657D94310cB8cE8B0D9a04541d8052 +export TESTING_AVAX_WORMHOLE_CHAINID=6 +export TESTING_AVAX_WORMHOLE_MESSAGE_FEE=0 +export TESTING_AVAX_WORMHOLE_GUARDIAN_SET_INDEX=3 +export TESTING_WRAPPED_AVAX_ADDRESS=0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7 + +############################################################################### +# +# Ethereum Mainnet +# +############################################################################### +export TESTING_ETH_FORK_RPC=https://mainnet.infura.io/v3/539d8f739090453abee027842bbd5671 +export TESTING_ETH_FORK_CHAINID=1 +export TESTING_ETH_WORMHOLE_ADDRESS=0x98f3c9e6E3fAce36bAAd05FE09d375Ef1464288B +export TESTING_ETH_BRIDGE_ADDRESS=0x3ee18B2214AFF97000D974cf647E7C347E8fa585 +export TESTING_ETH_WORMHOLE_CHAINID=2 +export TESTING_ETH_WORMHOLE_MESSAGE_FEE=0 +export TESTING_ETH_WORMHOLE_GUARDIAN_SET_INDEX=3 +export TESTING_WRAPPED_ETH_ADDRESS=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 From 824c8cd2a07b7de97a2c482516ec20815d7e0f3d Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Wed, 10 Apr 2024 17:14:32 -0400 Subject: [PATCH 05/28] testing --- src/wormhole/Message.sol | 1 + test/TestBridge.t.sol | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/wormhole/Message.sol b/src/wormhole/Message.sol index 6c3e899..0507a5e 100644 --- a/src/wormhole/Message.sol +++ b/src/wormhole/Message.sol @@ -27,6 +27,7 @@ abstract contract Message { parsedMessage.evmSender, parsedMessage.evmReceiver, parsedMessage.evmTokenAddress, + parsedMessage.evmTokenId, parsedMessage.solSender, parsedMessage.solReceiver, parsedMessage.solSenderTokenMint diff --git a/test/TestBridge.t.sol b/test/TestBridge.t.sol index 616e1a9..522ee32 100644 --- a/test/TestBridge.t.sol +++ b/test/TestBridge.t.sol @@ -39,17 +39,6 @@ contract TestBridge is Test { * contracts before each test is executed. */ function setUp() public { - // Fund accounts - vm.deal(sender, 100 ether); - vm.deal(receiver, 100 ether); - - apes = new Mocked721("Apes", "APE"); - birds = new Mocked721("Birds", "BIRD"); - - apes.safeMint(sender, 1); - - birds.safeMint(receiver, 1); - // verify that we're using the correct fork (AVAX mainnet in this case) require(block.chainid == vm.envUint("TESTING_AVAX_FORK_CHAINID"), "wrong evm"); @@ -78,6 +67,17 @@ contract TestBridge is Test { } function testAcceptTrade() public { + // Fund accounts + vm.deal(sender, 100 ether); + vm.deal(receiver, 100 ether); + + apes = new Mocked721("Apes", "APE"); + birds = new Mocked721("Birds", "BIRD"); + + apes.safeMint(sender, 1); + + birds.safeMint(receiver, 1); + // start listening to events vm.recordLogs(); @@ -115,6 +115,7 @@ contract TestBridge is Test { vm.stopPrank(); vm.startPrank(receiver); + assertEq(birds.ownerOf(1), receiver); echoSource.acceptOffer( "test", Offer({ From 4f305162cc2d54d85b1b92b5e3d6a2036dc5de05 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 6 May 2024 18:48:35 -0400 Subject: [PATCH 06/28] WIP update for EVM wormhole --- src/EchoCrossChain.sol | 16 +- src/EchoState.sol | 82 ++++++++ src/MessageValidator.sol | 29 ++- src/escrow/Escrow.sol | 13 +- src/escrow/EscrowData.sol | 23 -- src/escrow/EscrowHandler.sol | 28 ++- src/escrow/EscrowState.sol | 9 - src/types/Address.sol | 8 + src/types/Offer.sol | 22 ++ src/types/OfferItem.sol | 11 + src/types/OfferItems.sol | 10 + src/wormhole/WormholeData.sol | 41 ++-- src/wormhole/WormholeGovernance.sol | 27 ++- src/wormhole/WormholeState.sol | 18 +- test/TestBridge.t.sol | 316 +++++++++++++++------------- test/utils/EchoCrossChainTest.sol | 19 ++ 16 files changed, 410 insertions(+), 262 deletions(-) create mode 100644 src/EchoState.sol delete mode 100644 src/escrow/EscrowData.sol delete mode 100644 src/escrow/EscrowState.sol create mode 100644 src/types/Address.sol create mode 100644 src/types/Offer.sol create mode 100644 src/types/OfferItem.sol create mode 100644 src/types/OfferItems.sol create mode 100644 test/utils/EchoCrossChainTest.sol diff --git a/src/EchoCrossChain.sol b/src/EchoCrossChain.sol index c94ec7b..fad9b36 100644 --- a/src/EchoCrossChain.sol +++ b/src/EchoCrossChain.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.18; import "contracts/Admin.sol"; import "contracts/Banker.sol"; -import "contracts/Handler.sol"; import "contracts/MessageValidator.sol"; import "contracts/escrow/Escrow.sol"; import "contracts/wormhole/WormholeGovernance.sol"; @@ -24,6 +23,13 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover WormholeGovernance(wormhole, chainId, wormholeFinality) {} + function createOffer(Offer calldata offer) external payable nonReentrant notPaused { + // @dev Cannot accept an offer if not the receiver + if (offer.sender.ethAddress != msg.sender) { + revert InvalidCounterparty(); + } + } + // @dev This function assumes that the offer was created on another chain. function acceptOffer(string calldata offerId, Offer calldata offer, bytes memory encodedMessage) external @@ -34,7 +40,7 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover if (_offers[offerId].sender != address(0)) { revert OfferAlreadyExist(); } - // @dev + // @dev Cannot accept an offer if not the receiver if (offer.receiver != msg.sender) { revert InvalidCounterparty(); } @@ -48,7 +54,6 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover } // Validate that the offer was created on the other chain - // @dev This function will revert if not EchoMessage memory message = _receiveMessage(encodedMessage); _validateMessage(message, offer); @@ -114,4 +119,9 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover // trades[trade.id] = true; // emit TradeExecuted(trade.id); } + + // @dev Wormhole function to receive messages and update trades + function receiveMessage(bytes memory encodedMessage) public returns (EchoMessage memory parsedMessage) { + parsedMessage = _receiveMessage(encodedMessage); + } } diff --git a/src/EchoState.sol b/src/EchoState.sol new file mode 100644 index 0000000..eeaf8d5 --- /dev/null +++ b/src/EchoState.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/types/Offer.sol"; + +error OfferAlreadyExist(); +error OfferDoesNotExist(); +error OfferHasExpired(); +error InvalidAssets(); +error InvalidCounterparty(); +error InvalidCreator(); +error InvalidOfferState(); + +abstract contract EchoState { + mapping(string => Offer) internal _offers; + + // @dev Internal function to create the offer state. We don't do a check on the addresses here + // because it might be triggered from a cross chain call. The check is done in the main Echo contract + function _createOffer(Offer calldata offer) internal payable { + if (_offers[offer.id].sender != address(0)) { + revert OfferAlreadyExist(); + } + + if (offer.expiration <= block.timestamp) { + revert OfferHasExpired(); + } + if (offer.state != OfferState.OPEN) { + revert InvalidOfferState(); + } + + // @dev We validate that the offer data is valid + uint8 senderItemsLength = offer.senderItems.items.length; + if (offer.senderItems.count != senderItemsLength || senderItemsLength == 0) { + revert InvalidAssets(); + } + + uint8 receiverItemsLength = offer.receiverItems.items.length; + if (offer.receiverItems.count != receiverItemsLength || receiverItemsLength == 0) { + revert InvalidAssets(); + } + + _offers[offer.id] = offer; + } + + function _acceptOffer(string calldata offerId) internal { + if (_offers[offerId].sender == address(0)) { + revert OfferDoesNotExist(); + } + Offer offer = _offers[offerId]; + + // @dev Cannot accept an offer if not the receiver + if (offer.receiver.ethAddress != msg.sender) { + revert InvalidCounterparty(); + } + + if (offer.expiration <= block.timestamp) { + revert OfferHasExpired(); + } + // @dev Cannot accept an offer if it's not OPEN + if (offer.state != OfferState.OPEN) { + revert InvalidOfferState(); + } + _offers[offerId].state = OfferState.ACCEPTED; + } + + function _executeOffer(string calldata offerId) internal { + if (_offers[offerId].sender == address(0)) { + revert OfferDoesNotExist(); + } + Offer offer = _offers[offerId]; + + if (offer.expiration <= block.timestamp) { + revert OfferHasExpired(); + } + // @dev Cannot execute an offer if it's not ACCEPTED + if (offer.state != OfferState.ACCEPTED) { + revert InvalidOfferState(); + } + + delete _offers[offerId]; + } +} diff --git a/src/MessageValidator.sol b/src/MessageValidator.sol index c8cd895..6e99422 100644 --- a/src/MessageValidator.sol +++ b/src/MessageValidator.sol @@ -1,24 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/escrow/EscrowData.sol"; import "contracts/wormhole/WormholeData.sol"; error InvalidMessage(); abstract contract MessageValidator { - function _validateMessage(EchoMessage memory message, Offer calldata offer) internal { - if (address(uint160(uint256(message.evmSender))) != offer.sender) { - revert InvalidMessage(); - } - if (address(uint160(uint256(message.evmReceiver))) != offer.receiver) { - revert InvalidMessage(); - } - if (address(uint160(uint256(message.evmTokenAddress))) != offer.receiver721Asset.collection) { - revert InvalidMessage(); - } - if (message.evmTokenId != offer.receiver721Asset.id) { - revert InvalidMessage(); - } - } +// function _validateMessage(EchoMessage memory message, Offer calldata offer) internal { +// if (address(uint160(uint256(message.evmSender))) != offer.sender) { +// revert InvalidMessage(); +// } +// if (address(uint160(uint256(message.evmReceiver))) != offer.receiver) { +// revert InvalidMessage(); +// } +// if (address(uint160(uint256(message.evmTokenAddress))) != offer.receiver721Asset.collection) { +// revert InvalidMessage(); +// } +// if (message.evmTokenId != offer.receiver721Asset.id) { +// revert InvalidMessage(); +// } +// } } diff --git a/src/escrow/Escrow.sol b/src/escrow/Escrow.sol index 8991a5c..fa4e158 100644 --- a/src/escrow/Escrow.sol +++ b/src/escrow/Escrow.sol @@ -1,12 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/escrow/EscrowData.sol"; import "contracts/escrow/EscrowHandler.sol"; -import "contracts/escrow/EscrowState.sol"; +import "contracts/types/OfferItems.sol"; -abstract contract Escrow is EscrowState, EscrowHandler { - function _depositForReceiver(Offer calldata offer) internal { - _transferERC721(offer.receiver721Asset.collection, offer.receiver721Asset.id, offer.receiver, address(this)); +abstract contract Escrow is EscrowHandler { + function _deposit(OfferItems calldata offerItems, address from) internal { + _transferOfferItems(offerItems, from, address(this)); + } + + function _withdraw(OfferItems calldata offerItems, address to) internal { + _transferOfferItems(offerItems, address(this), to); } } diff --git a/src/escrow/EscrowData.sol b/src/escrow/EscrowData.sol deleted file mode 100644 index 9ef4202..0000000 --- a/src/escrow/EscrowData.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -struct ERC721Asset { - address collection; - uint64 id; -} - -// @dev For simplicity sake, we only support 1 asset and we assume the offer is -// always created on another chain, thus theres only receiver asset -struct Offer { - address sender; - address receiver; - uint256 expiresAt; - OfferStatus status; - ERC721Asset receiver721Asset; -} - -enum OfferStatus { - Created, - Accepted, - Cancelled -} diff --git a/src/escrow/EscrowHandler.sol b/src/escrow/EscrowHandler.sol index a41f8b8..e3d542f 100644 --- a/src/escrow/EscrowHandler.sol +++ b/src/escrow/EscrowHandler.sol @@ -1,16 +1,24 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/Handler.sol"; -import "forge-std/interfaces/IERC721.sol"; +import "solmate/tokens/ERC721.sol"; +import "contracts/types/OfferItems.sol"; -// -abstract contract EscrowHandler is Handler, IERC721TokenReceiver { - function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) - external - pure - returns (bytes4) - { - return this.onERC721Received.selector; +abstract contract EscrowHandler is ERC721TokenReceiver { + function _transferERC721(address collectionAddress, uint256 id, address from, address to) internal { + IERC721 collection = IERC721(collectionAddress); + collection.safeTransferFrom(from, to, id); + } + + // TODO add check for chain or size 0? + // @dev function to transfer items from an offer type + function _transferOfferItems(OfferItems calldata offerItems, address from, address to) internal { + uint8 length = offerItems.count; + for (uint8 i = 0; i < length;) { + _transferERC721(offerItems.items[i].tokenAddress.ethAddress, offerItems.items[i].tokenId, from, to); + unchecked { + i++; + } + } } } diff --git a/src/escrow/EscrowState.sol b/src/escrow/EscrowState.sol deleted file mode 100644 index 29fcb0a..0000000 --- a/src/escrow/EscrowState.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "contracts/escrow/EscrowData.sol"; - -abstract contract EscrowState { - mapping(string => bool) internal _executedTrades; - mapping(string => Offer) internal _offers; -} diff --git a/src/types/Address.sol b/src/types/Address.sol new file mode 100644 index 0000000..d49def8 --- /dev/null +++ b/src/types/Address.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +// @dev Struct to represent a multichain address +struct Address { + uint16 chainId; + address ethAddress; +} diff --git a/src/types/Offer.sol b/src/types/Offer.sol new file mode 100644 index 0000000..da54341 --- /dev/null +++ b/src/types/Offer.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/types/Address.sol"; +import "contracts/types/OfferItems.sol"; + +enum OfferState { + OPEN, + ACCEPTED +} + +// @dev Struct representing an on-chain offer +// TODO Should we store the id in the struct as it's already the key in the mapping +struct Offer { + string id; + Address sender; + Address receiver; + OfferItems senderItems; + OfferItems receiverItems; + uint64 expiration; + OfferState state; +} diff --git a/src/types/OfferItem.sol b/src/types/OfferItem.sol new file mode 100644 index 0000000..dbad1b0 --- /dev/null +++ b/src/types/OfferItem.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/types/Address.sol"; + +// @dev Struct representing an offer item (a token) +// @dev We only support ERC721 on EVM chains for now +struct OfferItem { + Address tokenAddress; + uint256 tokenId; +} diff --git a/src/types/OfferItems.sol b/src/types/OfferItems.sol new file mode 100644 index 0000000..6f541be --- /dev/null +++ b/src/types/OfferItems.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/types/OfferItem.sol"; + +// @dev Struct representing multiple offer items. We store the count for decoding purposes +struct OfferItems { + uint8 count; + OfferItem[] items; +} diff --git a/src/wormhole/WormholeData.sol b/src/wormhole/WormholeData.sol index ad4beee..0188341 100644 --- a/src/wormhole/WormholeData.sol +++ b/src/wormhole/WormholeData.sol @@ -1,34 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -// perhaps we should have a different struct for solana chain messages? -struct EchoMessage { - // unique identifier for this message type - uint8 payloadID; - // @dev id of the offer - string id; - // @dev EVM specific message - bytes32 evmSender; - bytes32 evmReceiver; - bytes32 evmTokenAddress; - uint64 evmTokenId; - // @dev Solana specific message - bytes32 solSender; - bytes32 solReceiver; - bytes32 solSenderTokenMint; +struct OfferCreatedMessage { + string offerId; + Address sender; + Address receiver; + OfferItems[] senderItems; + OfferItems[] receiverItems; + uint64 expiration; } -// TODO Optimize this -struct EchoMessageWithoutPayload { - // @dev id of the offer - string id; - // @dev EVM specific message - bytes32 evmSender; - bytes32 evmReceiver; - bytes32 evmTokenAddress; - uint64 evmTokenId; - // @dev Solana specific message - bytes32 solSender; - bytes32 solReceiver; - bytes32 solSenderTokenMint; +struct OfferAcceptedMessage { + string offerId; +} + +struct OfferCancelledMessage { + string offerId; } diff --git a/src/wormhole/WormholeGovernance.sol b/src/wormhole/WormholeGovernance.sol index 12859f6..b259612 100644 --- a/src/wormhole/WormholeGovernance.sol +++ b/src/wormhole/WormholeGovernance.sol @@ -32,16 +32,11 @@ abstract contract WormholeGovernance is Owned, Message, WormholeState { * @param message EchoMessageWithoutPayload to send * @return messageSequence Wormhole message sequence for this contract */ - function _sendMessage(EchoMessageWithoutPayload memory message) public payable returns (uint64 messageSequence) { - IWormhole wormhole = wormholeContract(); - uint256 wormholeFee = wormhole.messageFee(); - - // TODO Add checks on the message? - - if (msg.value != wormholeFee) { - revert NotEnoughWormholeFees(); - } - + function _sendMessage(EchoMessageWithoutPayload memory message) + internal + hasEnoughWormholeFees + returns (uint64 messageSequence) + { EchoMessage memory parsedMessage = EchoMessage({ payloadID: uint8(1), id: message.id, @@ -76,7 +71,7 @@ abstract contract WormholeGovernance is Owned, Message, WormholeState { * @param encodedMessage verified Wormhole message containing arbitrary * @return parsedMessage EchoMessage The parsed message from Wormhole */ - function _receiveMessage(bytes memory encodedMessage) public returns (EchoMessage memory parsedMessage) { + function receiveMessage(bytes memory encodedMessage) internal returns (EchoMessage memory parsedMessage) { // call the Wormhole core contract to parse and verify the encodedMessage (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = wormholeContract().parseAndVerifyVM(encodedMessage); @@ -97,4 +92,14 @@ abstract contract WormholeGovernance is Owned, Message, WormholeState { } _consumeMessage(wormholeMessage.hash); } + + modifier hasEnoughWormholeFees() { + IWormhole wormhole = wormholeContract(); + uint256 wormholeFee = wormhole.messageFee(); + + if (msg.value != wormholeFee) { + revert NotEnoughWormholeFees(); + } + _; + } } diff --git a/src/wormhole/WormholeState.sol b/src/wormhole/WormholeState.sol index 0571ab5..9074b47 100644 --- a/src/wormhole/WormholeState.sol +++ b/src/wormhole/WormholeState.sol @@ -29,23 +29,15 @@ struct State { abstract contract WormholeState is Owned { State internal _state; - function isMessageConsumed(bytes32 hash) public view returns (bool) { + function isMessageConsumed(bytes32 hash) external view returns (bool) { return _state.consumedMessages[hash]; } - function wormholeContract() public view returns (IWormhole) { + function wormholeContract() external view returns (IWormhole) { return IWormhole(_state.wormhole); } - // function _setEmitter(uint16 chainId, bytes32 emitter) internal { - // _state.registeredEmitters[chainId] = emitter; - // } - - function _consumeMessage(bytes32 hash) internal { - _state.consumedMessages[hash] = true; - } - - function chainId() public view returns (uint16) { + function chainId() external view returns (uint16) { return _state.chainId; } @@ -69,6 +61,10 @@ abstract contract WormholeState is Owned { _state.registeredEmitters[emitterChainId] = emitterAddress; } + function _consumeMessage(bytes32 hash) internal { + _state.consumedMessages[hash] = true; + } + function _verifyEmitter(IWormhole.VM memory vm) internal view returns (bool) { return _state.registeredEmitters[vm.emitterChainId] == vm.emitterAddress; } diff --git a/test/TestBridge.t.sol b/test/TestBridge.t.sol index 522ee32..b75ad56 100644 --- a/test/TestBridge.t.sol +++ b/test/TestBridge.t.sol @@ -1,147 +1,169 @@ -// SPDX-License-Identifier: Apache 2 -pragma solidity ^0.8.18; - -import "forge-std/Test.sol"; -import "forge-std/console.sol"; -import "./mock/Mocked721.t.sol"; -import "./utils/WormholeSimulator.sol"; -import "contracts/EchoCrossChain.sol"; -import "contracts/escrow/EscrowData.sol"; -import "contracts/wormhole/WormholeData.sol"; - -/** - * @title A Test Suite for the EVM EchoCrossChain Contracts - */ -contract TestBridge is Test { - // guardian private key for simulated signing of Wormhole messages - uint256 guardianSigner; - - // contract instances - IWormhole wormhole; - WormholeSimulator wormholeSimulator; - EchoCrossChain echoSource; - EchoCrossChain echoTarget; - - address public constant owner = address(1313); - address public constant sender = address(1337); - address public constant receiver = address(1339); - - Mocked721 public apes; - Mocked721 public birds; - - address public apeAddress; - uint256 public ape1Id; - address public birdAddress; - uint256 public bird1Id; - - /** - * @notice Sets up the wormholeSimulator contracts and deploys HelloWorld - * contracts before each test is executed. - */ - function setUp() public { - // verify that we're using the correct fork (AVAX mainnet in this case) - require(block.chainid == vm.envUint("TESTING_AVAX_FORK_CHAINID"), "wrong evm"); - - // this will be used to sign Wormhole messages - guardianSigner = uint256(vm.envBytes32("TESTING_DEVNET_GUARDIAN")); - - // we may need to interact with Wormhole throughout the test - wormhole = IWormhole(vm.envAddress("TESTING_AVAX_WORMHOLE_ADDRESS")); - - // set up Wormhole using Wormhole existing on AVAX mainnet - wormholeSimulator = new SigningWormholeSimulator(wormhole, guardianSigner); - - // verify Wormhole state from fork - require(wormhole.chainId() == uint16(vm.envUint("TESTING_AVAX_WORMHOLE_CHAINID")), "wrong chainId"); - require(wormhole.messageFee() == vm.envUint("TESTING_AVAX_WORMHOLE_MESSAGE_FEE"), "wrong messageFee"); - require( - wormhole.getCurrentGuardianSetIndex() == uint32(vm.envUint("TESTING_AVAX_WORMHOLE_GUARDIAN_SET_INDEX")), - "wrong guardian set index" - ); - - echoSource = new EchoCrossChain(address(owner), address(wormhole), wormhole.chainId(), uint8(1)); - echoTarget = new EchoCrossChain(address(owner), address(wormhole), uint8(2), uint8(1)); - - // confirm that the source and target contract addresses are different - assertTrue(address(echoSource) != address(echoTarget)); - } - - function testAcceptTrade() public { - // Fund accounts - vm.deal(sender, 100 ether); - vm.deal(receiver, 100 ether); - - apes = new Mocked721("Apes", "APE"); - birds = new Mocked721("Birds", "BIRD"); - - apes.safeMint(sender, 1); - - birds.safeMint(receiver, 1); - - // start listening to events - vm.recordLogs(); - - bytes32 evmSender = bytes32(uint256(uint160(sender)) << 96); - bytes32 evmReceiver = bytes32(uint256(uint160(receiver)) << 96); - bytes32 evmTokenAddress = bytes32(uint256(uint160(address(birds))) << 96); - uint64 evmTokenId = uint64(1); - bytes32 solSender = bytes32(0); - bytes32 solReceiver = bytes32(0); - bytes32 solSenderTokenMint = bytes32(0); - - EchoMessageWithoutPayload memory message = EchoMessageWithoutPayload({ - id: "test", - evmSender: evmSender, - evmReceiver: evmReceiver, - evmTokenAddress: evmTokenAddress, - evmTokenId: evmTokenId, - solSender: solSender, - solReceiver: solReceiver, - solSenderTokenMint: solSenderTokenMint - }); - echoTarget._sendMessage(message); - - // record the emitted wormhole message - Vm.Log[] memory entries = vm.getRecordedLogs(); - - // simulate signing the Wormhole message - // NOTE: in the wormhole-sdk, signed Wormhole messages are referred to as signed VAAs - bytes memory encodedMessage = - wormholeSimulator.fetchSignedMessageFromLogs(entries[0], echoTarget.chainId(), address(echoTarget)); - - vm.startPrank(owner); - // register the emitter on the source contract - echoSource.registerEmitter(echoTarget.chainId(), bytes32(uint256(uint160(address(echoTarget))))); - vm.stopPrank(); - - vm.startPrank(receiver); - assertEq(birds.ownerOf(1), receiver); - echoSource.acceptOffer( - "test", - Offer({ - sender: sender, - receiver: receiver, - expiresAt: block.timestamp + (60 * 60 * 6), - status: OfferStatus.Created, - receiver721Asset: ERC721Asset({collection: address(birds), id: evmTokenId}) - }), - encodedMessage - ); - - // Parse the encodedMessage to retrieve the hash. This is a safe operation - // since the source HelloWorld contract already verfied the message in the - // previous call. - IWormhole.VM memory parsedMessage = wormhole.parseVM(encodedMessage); - - // Verify that the message was consumed and the payload was saved - // in the contract state. - bool messageWasConsumed = echoSource.isMessageConsumed(parsedMessage.hash); - - assertTrue(messageWasConsumed); - - // Confirm that message replay protection works by trying to call receiveMessage - // with the same Wormhole message again. - vm.expectRevert("message already consumed"); - echoSource._receiveMessage(encodedMessage); - } -} +//// SPDX-License-Identifier: Apache 2 +//pragma solidity ^0.8.18; +// +//import "./utils/WormholeSimulator.sol"; +//import "./utils/EchoCrossChainTest.sol"; +//import "contracts/wormhole/WormholeData.sol"; +//import "contracts/wormhole/WormholeError.sol"; +//import "forge-std/Test.sol"; +//import "forge-std/console.sol"; +//import "solmate/test/utils/mocks/MockERC721.sol"; +// +///** +// * @title A Test Suite for the EVM EchoCrossChain Contracts +// */ +//contract TestBridge is Test { +// // guardian private key for simulated signing of Wormhole messages +// uint256 guardianSigner; +// +// // contract instances +// IWormhole wormhole; +// WormholeSimulator wormholeSimulator; +// EchoCrossChainTest echoSource; +// EchoCrossChainTest echoTarget; +// +// address public constant owner = address(1313); +// address public constant sender = address(1337); +// address public constant receiver = address(1339); +// +// MockERC721 public apes; +// MockERC721 public birds; +// +// address public apeAddress; +// uint256 public ape1Id; +// address public birdAddress; +// uint256 public bird1Id; +// +// /** +// * @notice Sets up the wormholeSimulator contracts and deploys HelloWorld +// * contracts before each test is executed. +// */ +// function setUp() public { +// vm.deal(sender, 100 ether); +// vm.deal(receiver, 100 ether); +// +// apes = new MockERC721("Apes", "APE"); +// birds = new MockERC721("Birds", "BIRD"); +// +// apes.safeMint(sender, 1); +// birds.safeMint(receiver, 1); +// +// /* Initialize wormhole */ +// // verify that we're using the correct fork (AVAX mainnet in this case) +// require(block.chainid == vm.envUint("TESTING_AVAX_FORK_CHAINID"), "wrong evm"); +// +// // this will be used to sign Wormhole messages +// guardianSigner = uint256(vm.envBytes32("TESTING_DEVNET_GUARDIAN")); +// +// // we may need to interact with Wormhole throughout the test +// wormhole = IWormhole(vm.envAddress("TESTING_AVAX_WORMHOLE_ADDRESS")); +// +// // set up Wormhole using Wormhole existing on AVAX mainnet +// wormholeSimulator = new SigningWormholeSimulator(wormhole, guardianSigner); +// +// // verify Wormhole state from fork +// require( +// wormhole.chainId() == uint16(vm.envUint("TESTING_AVAX_WORMHOLE_CHAINID")), +// "wrong chainId" +// ); +// require( +// wormhole.messageFee() == vm.envUint("TESTING_AVAX_WORMHOLE_MESSAGE_FEE"), +// "wrong messageFee" +// ); +// require( +// wormhole.getCurrentGuardianSetIndex() == +// uint32(vm.envUint("TESTING_AVAX_WORMHOLE_GUARDIAN_SET_INDEX")), +// "wrong guardian set index" +// ); +// +// echoSource = new EchoCrossChainTest( +// address(owner), +// address(wormhole), +// wormhole.chainId(), +// uint8(1) +// ); +// echoTarget = new EchoCrossChainTest(address(owner), address(wormhole), uint8(2), uint8(1)); +// +// // confirm that the source and target contract addresses are different +// assertTrue(address(echoSource) != address(echoTarget)); +// } +// +// function testTransfer() public { +// assertEq(birds.ownerOf(1), receiver); +// vm.prank(receiver); +// birds.safeTransferFrom(receiver, address(echoTarget), 1); +// assertEq(birds.ownerOf(1), address(echoTarget)); +// } +// +// function testAcceptTrade() public { +// // start listening to events +// vm.recordLogs(); +// +// bytes32 evmSender = bytes32(uint256(uint160(sender)) << 96); +// bytes32 evmReceiver = bytes32(uint256(uint160(receiver)) << 96); +// bytes32 evmTokenAddress = bytes32(uint256(uint160(address(birds))) << 96); +// uint64 evmTokenId = uint64(1); +// bytes32 solSender = bytes32(0); +// bytes32 solReceiver = bytes32(0); +// bytes32 solSenderTokenMint = bytes32(0); +// +// EchoMessageWithoutPayload memory message = EchoMessageWithoutPayload({ +// id: "test", +// evmSender: evmSender, +// evmReceiver: evmReceiver, +// evmTokenAddress: evmTokenAddress, +// evmTokenId: evmTokenId, +// solSender: solSender, +// solReceiver: solReceiver, +// solSenderTokenMint: solSenderTokenMint +// }); +// echoTarget.sendMessage(message); +// +// // record the emitted wormhole message +// Vm.Log[] memory entries = vm.getRecordedLogs(); +// +// // simulate signing the Wormhole message +// // NOTE: in the wormhole-sdk, signed Wormhole messages are referred to as signed VAAs +// bytes memory encodedMessage = wormholeSimulator.fetchSignedMessageFromLogs( +// entries[0], +// echoTarget.chainId(), +// address(echoTarget) +// ); +// +// vm.startPrank(owner); +// // register the emitter on the source contract +// echoSource.registerEmitter( +// echoTarget.chainId(), +// bytes32(uint256(uint160(address(echoTarget)))) +// ); +// vm.stopPrank(); +// +// vm.startPrank(receiver); +// birds.approve(address(echoSource), 1); +// echoSource.acceptOffer( +// "test", +// Offer({ +// sender: sender, +// receiver: receiver, +// expiresAt: block.timestamp + (60 * 60 * 6), +// status: OfferStatus.Created, +// receiver721Asset: ERC721Asset({collection: address(birds), id: evmTokenId}) +// }), +// encodedMessage +// ); +// +// // Parse the encodedMessage to retrieve the hash. This is a safe operation +// // since the source HelloWorld contract already verfied the message in the +// // previous call. +// IWormhole.VM memory parsedMessage = wormhole.parseVM(encodedMessage); +// +// // Verify that the message was consumed and the payload was saved +// // in the contract state. +// bool messageWasConsumed = echoSource.isMessageConsumed(parsedMessage.hash); +// +// assertTrue(messageWasConsumed); +// +// vm.expectRevert(MessageAlreadyConsumed.selector); +// echoSource.receiveMessage(encodedMessage); +// } +//} diff --git a/test/utils/EchoCrossChainTest.sol b/test/utils/EchoCrossChainTest.sol new file mode 100644 index 0000000..1580741 --- /dev/null +++ b/test/utils/EchoCrossChainTest.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "contracts/EchoCrossChain.sol"; +import "contracts/wormhole/WormholeData.sol"; + +contract EchoCrossChainTest is EchoCrossChain { + constructor(address owner, address wormhole, uint16 chainId, uint8 wormholeFinality) + EchoCrossChain(owner, wormhole, chainId, wormholeFinality) + {} + + function sendMessage(EchoMessageWithoutPayload memory message) public payable returns (uint64 messageSequence) { + return _sendMessage(message); + } + + function receiveMessage(bytes memory encodedMessage) public returns (EchoMessage memory parsedMessage) { + return _receiveMessage(encodedMessage); + } +} From 0942ff3bc4b77cede9ee7600213494730541033b Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Tue, 7 May 2024 15:44:33 -0400 Subject: [PATCH 07/28] started cleaning code for wormhole version --- script/DeployERC721.s.sol | 2 +- script/DeployEcho.s.sol | 20 --- script/DeployEchoMainnet.s.sol | 20 --- script/DeployTestEcho.s.sol | 20 --- script/MintNfts.s.sol | 2 +- script/TestSignerSignature.s.sol | 42 ------ src/AdminSigner.sol | 35 ----- src/Echo.sol | 76 ---------- src/EchoCrossChain.sol | 109 ++++++++------- src/EchoState.sol | 121 ++++++++++++---- src/Handler.sol | 24 ---- src/MessageValidator.sol | 2 - src/Signer.sol | 81 ----------- src/TestEcho.sol | 27 ---- src/escrow/EscrowHandler.sol | 4 +- src/types/Address.sol | 8 -- src/types/Offer.sol | 7 +- src/types/OfferItem.sol | 4 +- src/types/OfferItems.sol | 2 +- src/wormhole/Message.sol | 133 +++++++++--------- src/wormhole/MessageTypes.sol | 40 ++++++ src/wormhole/WormholeData.sol | 19 --- src/wormhole/WormholeGovernance.sol | 139 +++++++++---------- src/wormhole/WormholeState.sol | 2 +- test/Admin.t.sol | 14 +- test/Approval.t.sol | 2 +- test/Banker.t.sol | 89 ++++++++++++ test/BaseTest.t.sol | 118 +++++++--------- test/Expiration.t.sol | 2 +- test/Fees.t.sol | 2 +- test/MockTradeExecution.t.sol | 58 -------- test/Ownership.t.sol | 2 +- test/Signature.t.sol | 2 +- test/TestBridge.t.sol | 4 +- test/Trade721.t.sol | 2 +- test/mock/MockHandler.sol | 6 + test/mock/MockHandler.t.sol | 10 -- test/{utils => mock}/MockWormhole.sol | 0 test/mock/{Mocked721.t.sol => Mocked721.sol} | 0 test/{utils => mock}/WormholeSimulator.sol | 7 +- test/utils/Constants.sol | 20 --- test/utils/EchoCrossChainTest.sol | 19 --- 42 files changed, 497 insertions(+), 799 deletions(-) delete mode 100644 script/DeployEcho.s.sol delete mode 100644 script/DeployEchoMainnet.s.sol delete mode 100644 script/DeployTestEcho.s.sol delete mode 100644 script/TestSignerSignature.s.sol delete mode 100644 src/AdminSigner.sol delete mode 100644 src/Echo.sol delete mode 100644 src/Handler.sol delete mode 100644 src/Signer.sol delete mode 100644 src/TestEcho.sol delete mode 100644 src/types/Address.sol create mode 100644 src/wormhole/MessageTypes.sol delete mode 100644 src/wormhole/WormholeData.sol create mode 100644 test/Banker.t.sol delete mode 100644 test/MockTradeExecution.t.sol create mode 100644 test/mock/MockHandler.sol delete mode 100644 test/mock/MockHandler.t.sol rename test/{utils => mock}/MockWormhole.sol (100%) rename test/mock/{Mocked721.t.sol => Mocked721.sol} (100%) rename test/{utils => mock}/WormholeSimulator.sol (99%) delete mode 100644 test/utils/Constants.sol delete mode 100644 test/utils/EchoCrossChainTest.sol diff --git a/script/DeployERC721.s.sol b/script/DeployERC721.s.sol index 60fb3ad..dbddde6 100644 --- a/script/DeployERC721.s.sol +++ b/script/DeployERC721.s.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "forge-std/Script.sol"; -import "../test/mock/Mocked721.t.sol"; +import "../test/mock/Mocked721.sol"; contract DeployNFT is Script { // Exclude from coverage report diff --git a/script/DeployEcho.s.sol b/script/DeployEcho.s.sol deleted file mode 100644 index 4c47d25..0000000 --- a/script/DeployEcho.s.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "forge-std/Script.sol"; -import "../src/Echo.sol"; - -contract DeployEcho is Script { - // Exclude from coverage report - function test() public {} - - function run() external { - vm.startBroadcast(); - new Echo({ - owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), - signer: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09) - }); - - vm.stopBroadcast(); - } -} diff --git a/script/DeployEchoMainnet.s.sol b/script/DeployEchoMainnet.s.sol deleted file mode 100644 index 78937d4..0000000 --- a/script/DeployEchoMainnet.s.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "forge-std/Script.sol"; -import "../src/Echo.sol"; - -contract DeployEcho is Script { - // Exclude from coverage report - function test() public {} - - function run() external { - vm.startBroadcast(); - new Echo({ - owner: address(0x89eb616B4443783c160E7Cd82E56bfc66A545CeF), - signer: address(0x89eb616B4443783c160E7Cd82E56bfc66A545CeF) - }); - - vm.stopBroadcast(); - } -} diff --git a/script/DeployTestEcho.s.sol b/script/DeployTestEcho.s.sol deleted file mode 100644 index 7724640..0000000 --- a/script/DeployTestEcho.s.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "forge-std/Script.sol"; -import "../src/TestEcho.sol"; - -contract DeployTestEcho is Script { - // Exclude from coverage report - function test() public {} - - function run() external { - vm.startBroadcast(); - - new TestEcho({ - owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), - signer: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09) - }); - vm.stopBroadcast(); - } -} diff --git a/script/MintNfts.s.sol b/script/MintNfts.s.sol index 7576600..d9fce77 100644 --- a/script/MintNfts.s.sol +++ b/script/MintNfts.s.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "forge-std/Script.sol"; -import "../test/mock/Mocked721.t.sol"; +import "../test/mock/Mocked721.sol"; contract MintNfts is Script { // Exclude from coverage report diff --git a/script/TestSignerSignature.s.sol b/script/TestSignerSignature.s.sol deleted file mode 100644 index 6220e34..0000000 --- a/script/TestSignerSignature.s.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "forge-std/Script.sol"; -import "../src/TestEcho.sol"; -import "../test/utils/Constants.sol"; - -contract TestSignerSignature is Script { - // Exclude from coverage report - function test() public {} - - function _splitSignature(bytes memory sig) internal pure returns (bytes32 r, bytes32 s, uint8 v) { - require(sig.length == 65, "invalid signature length"); - assembly { - r := mload(add(sig, 32)) - // second 32 bytes - s := mload(add(sig, 64)) - // final byte (first byte of the next 32 bytes) - v := byte(0, mload(add(sig, 96))) - } - } - - function run() external { - vm.startBroadcast(); - // Use existing contract - TestEcho echo = TestEcho(0x7dfC7f96c967C9e00988D6Bf78da64939B1CC634); - - bytes memory offerSignature = - hex"b180fe5c8980be7a4bcfb11bc1a113600879da7053b2bedb8984e350d8231221702acd0bb3894f67ebc7d7bc52aefb23f4f0bc96e161e38efb95640016c0f9721c"; - - (bytes32 rOffer, bytes32 sOffer, uint8 vOffer) = _splitSignature(offerSignature); - bytes32 hashStruct = keccak256(abi.encode(SIGNATURE_TYPEHASH, vOffer, rOffer, sOffer)); - bytes32 digest = keccak256(abi.encodePacked("\x19\x01", echo.domainSeparator(), hashStruct)); - // @dev since we're using an existing contract, we need to use the signer key here. - // Simply add the proper one and use the script, but make sure it's not committed. - (uint8 v, bytes32 r, bytes32 s) = vm.sign(0xB0B, digest); - Signature memory signature = Signature({v: vOffer, r: rOffer, s: sOffer}); - echo.executeTrade(v, r, s, signature); - - vm.stopBroadcast(); - } -} diff --git a/src/AdminSigner.sol b/src/AdminSigner.sol deleted file mode 100644 index 0df5d03..0000000 --- a/src/AdminSigner.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "solmate/auth/Owned.sol"; - -error Paused(); -error InvalidAddress(); - -/// @dev Handles ownable and pausable of contract. -/// Also manages the signer address to validate trades -abstract contract AdminSigner is Owned { - bool public paused; - address public signer; - - constructor(address owner, address _signer) Owned(owner) { - signer = _signer; - } - - function setPaused(bool _paused) external onlyOwner { - paused = _paused; - } - - function setSigner(address _signer) external onlyOwner { - if (_signer == address(0)) revert InvalidAddress(); - signer = _signer; - } - - modifier notPaused() { - if (paused) { - revert Paused(); - } - - _; - } -} diff --git a/src/Echo.sol b/src/Echo.sol deleted file mode 100644 index 067d340..0000000 --- a/src/Echo.sol +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "contracts/AdminSigner.sol"; -import "contracts/Banker.sol"; -import "contracts/Handler.sol"; -import "contracts/Signer.sol"; -import "solmate/utils/ReentrancyGuard.sol"; - -error TradeAlreadyExist(); -error TradeHasExpired(); -error InvalidCreator(); -error InvalidAssets(); -error InvalidPayment(); - -contract Echo is ReentrancyGuard, AdminSigner, Handler, Banker, Signer { - event TradeExecuted(string id); - - constructor(address owner, address signer) AdminSigner(owner, signer) {} - - /// @dev Only executed trades are on chain to avoid replay attacks - /// Trades are mapped by id - mapping(string => bool) internal trades; - - function executeTrade(uint8 v, bytes32 r, bytes32 s, Signature calldata signatureData, Trade calldata trade) - external - payable - nonReentrant - notPaused - { - if (trades[trade.id]) { - revert TradeAlreadyExist(); - } - - if (trade.creator != msg.sender) { - revert InvalidCreator(); - } - - // We only check that length is not 0 here because we check the length in the transfer method - if (trade.creatorCollections.length == 0 || trade.counterpartyCollections.length == 0) { - revert InvalidAssets(); - } - - if (trade.expiresAt <= block.timestamp) { - revert TradeHasExpired(); - } - - if (msg.value != tradingFee) { - revert InvalidPayment(); - } - - _validateSignature(v, r, s, signatureData, signer); - _validateTrade(signatureData, trade); - - // Transfer creator's assets - _transferTokens({ - collections: trade.creatorCollections, - ids: trade.creatorIds, - from: trade.creator, - to: trade.counterparty - }); - - // Transfer counterparty's assets - _transferTokens({ - collections: trade.counterpartyCollections, - ids: trade.counterpartyIds, - from: trade.counterparty, - to: trade.creator - }); - - // Add trade to list to avoid replay and duplicates - trades[trade.id] = true; - - emit TradeExecuted(trade.id); - } -} diff --git a/src/EchoCrossChain.sol b/src/EchoCrossChain.sol index fad9b36..bd87e71 100644 --- a/src/EchoCrossChain.sol +++ b/src/EchoCrossChain.sol @@ -3,30 +3,39 @@ pragma solidity ^0.8.18; import "contracts/Admin.sol"; import "contracts/Banker.sol"; +import "contracts/EchoState.sol"; import "contracts/MessageValidator.sol"; import "contracts/escrow/Escrow.sol"; +import "contracts/types/Offer.sol"; import "contracts/wormhole/WormholeGovernance.sol"; import "solmate/utils/ReentrancyGuard.sol"; -error OfferAlreadyExist(); -error OfferHasExpired(); -error InvalidOfferStatus(); -error InvalidCounterparty(); -error InvalidAssets(); +error InvalidSender(); +error InvalidReceiver(); error InvalidPayment(); -contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGovernance, MessageValidator { - event TradeExecuted(string id); - +contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGovernance, EchoState, MessageValidator { constructor(address owner, address wormhole, uint16 chainId, uint8 wormholeFinality) Admin(owner) WormholeGovernance(wormhole, chainId, wormholeFinality) {} + /** + * Same chain offers + */ function createOffer(Offer calldata offer) external payable nonReentrant notPaused { // @dev Cannot accept an offer if not the receiver - if (offer.sender.ethAddress != msg.sender) { - revert InvalidCounterparty(); + if (offer.sender != msg.sender) { + revert InvalidSender(); + } + _deposit(offer.senderItems, offer.sender); + _createOffer(offer, _state.chainId); + } + + function createCrossChainOffer(Offer calldata offer) external payable nonReentrant notPaused { + // @dev Cannot accept an offer if not the receiver + if (offer.sender != msg.sender) { + revert InvalidSender(); } } @@ -37,41 +46,41 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover nonReentrant notPaused { - if (_offers[offerId].sender != address(0)) { - revert OfferAlreadyExist(); - } - // @dev Cannot accept an offer if not the receiver - if (offer.receiver != msg.sender) { - revert InvalidCounterparty(); - } - - if (offer.expiresAt <= block.timestamp) { - revert OfferHasExpired(); - } - - if (offer.status != OfferStatus.Created) { - revert InvalidOfferStatus(); - } - - // Validate that the offer was created on the other chain - EchoMessage memory message = _receiveMessage(encodedMessage); - _validateMessage(message, offer); - - _depositForReceiver(offer); - _offers[offerId] = offer; - - // @dev FIXME the message should change - EchoMessageWithoutPayload memory newMessage = EchoMessageWithoutPayload({ - id: message.id, - evmSender: message.evmSender, - evmReceiver: message.evmReceiver, - evmTokenAddress: message.evmTokenAddress, - evmTokenId: message.evmTokenId, - solSender: message.solSender, - solReceiver: message.solReceiver, - solSenderTokenMint: message.solSenderTokenMint - }); - _sendMessage(newMessage); + // if (_offers[offerId].sender != address(0)) { + // revert OfferAlreadyExist(); + // } + // // @dev Cannot accept an offer if not the receiver + // if (offer.receiver != msg.sender) { + // revert InvalidCounterparty(); + // } + // + // if (offer.expiresAt <= block.timestamp) { + // revert OfferHasExpired(); + // } + // + // if (offer.status != OfferStatus.Created) { + // revert InvalidOfferStatus(); + // } + // + // // Validate that the offer was created on the other chain + // EchoMessage memory message = _receiveMessage(encodedMessage); + // _validateMessage(message, offer); + // + // _depositForReceiver(offer); + // _offers[offerId] = offer; + // + // // @dev FIXME the message should change + // EchoMessageWithoutPayload memory newMessage = EchoMessageWithoutPayload({ + // id: message.id, + // evmSender: message.evmSender, + // evmReceiver: message.evmReceiver, + // evmTokenAddress: message.evmTokenAddress, + // evmTokenId: message.evmTokenId, + // solSender: message.solSender, + // solReceiver: message.solReceiver, + // solSenderTokenMint: message.solSenderTokenMint + // }); + // _sendMessage(newMessage); } function executeTrade() external payable nonReentrant notPaused { @@ -120,8 +129,10 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover // emit TradeExecuted(trade.id); } - // @dev Wormhole function to receive messages and update trades - function receiveMessage(bytes memory encodedMessage) public returns (EchoMessage memory parsedMessage) { - parsedMessage = _receiveMessage(encodedMessage); - } + // // @dev Wormhole function to receive messages and update trades + // function receiveMessage( + // bytes memory encodedMessage + // ) public returns (EchoMessage memory parsedMessage) { + // parsedMessage = _receiveMessage(encodedMessage); + // } } diff --git a/src/EchoState.sol b/src/EchoState.sol index eeaf8d5..4b073bd 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -2,72 +2,123 @@ pragma solidity ^0.8.18; import "contracts/types/Offer.sol"; +import "contracts/types/OfferItem.sol"; error OfferAlreadyExist(); error OfferDoesNotExist(); error OfferHasExpired(); error InvalidAssets(); -error InvalidCounterparty(); -error InvalidCreator(); error InvalidOfferState(); abstract contract EchoState { - mapping(string => Offer) internal _offers; + mapping(bytes32 => Offer) public offers; - // @dev Internal function to create the offer state. We don't do a check on the addresses here - // because it might be triggered from a cross chain call. The check is done in the main Echo contract - function _createOffer(Offer calldata offer) internal payable { - if (_offers[offer.id].sender != address(0)) { + /** + * Utils + */ + function _generateOfferId(Offer calldata offer) internal returns (bytes32 offerId) { + // TODO Validate this behaviour + offerId = keccak256( + abi.encode( + offer.sender, + offer.receiver, + offer.senderItems.chainId, + keccak256(abi.encodePacked(offer.senderItems.items)), // OfferItem[] + offer.receiverItems.chainId, + keccak256(abi.encodePacked(offer.receiverItems.items)), // OfferItem[] + offer.expiration + ) + ); + } + + // @dev Internal function to check that offer data is valid for creation + function _validateOffer(bytes32 offerId, Offer calldata offer) internal offerNotExpired(offer.expiration) { + if (offers[offerId].sender != address(0)) { revert OfferAlreadyExist(); } - if (offer.expiration <= block.timestamp) { - revert OfferHasExpired(); - } if (offer.state != OfferState.OPEN) { revert InvalidOfferState(); } - // @dev We validate that the offer data is valid - uint8 senderItemsLength = offer.senderItems.items.length; - if (offer.senderItems.count != senderItemsLength || senderItemsLength == 0) { + if (offer.senderItems.items.length == 0) { revert InvalidAssets(); } - uint8 receiverItemsLength = offer.receiverItems.items.length; - if (offer.receiverItems.count != receiverItemsLength || receiverItemsLength == 0) { + if (offer.receiverItems.items.length == 0) { revert InvalidAssets(); } + } + + /** + * Same chain offers + */ + // @dev Internal function to create a same chain offer + function _createOffer(Offer calldata offer, uint16 chainId) internal { + bytes32 offerId = _generateOfferId(offer); - _offers[offer.id] = offer; + _validateOffer(offerId, offer); + + // @dev Chain must be the same as contract for same chain offers + if (offer.senderItems.chainId != chainId) { + revert InvalidAssets(); + } + + // @dev Chain must be the same as contract for same chain offers + if (offer.receiverItems.chainId != chainId) { + revert InvalidAssets(); + } + + offers[offerId] = offer; } - function _acceptOffer(string calldata offerId) internal { - if (_offers[offerId].sender == address(0)) { - revert OfferDoesNotExist(); + function _acceptOffer(Offer calldata offer, uint16 chainId) internal {} + + // @dev Internal function to create a cross chain offer. We don't do a check on the addresses here + // because it might be triggered from a cross chain call. The check is done in the main Echo contract + function _createCrossChainOffer(Offer calldata offer, uint16 chainId) internal { + bytes32 offerId = _generateOfferId(offer); + + _validateOffer(offerId, offer); + + // @dev Chain must be the same as contract for sender items on cross chain offers + if (offer.senderItems.chainId != chainId) { + revert InvalidAssets(); + } + + // @dev Cannot create a cross chain offer on the same chain + if (offer.receiverItems.chainId == chainId) { + revert InvalidAssets(); } - Offer offer = _offers[offerId]; - // @dev Cannot accept an offer if not the receiver - if (offer.receiver.ethAddress != msg.sender) { - revert InvalidCounterparty(); + offers[offerId] = offer; + } + + // @dev Internal function to accept the offer. We don't do a check on the addresses here + // because it might be triggered from a cross chain call. The check is done in the main Echo contract + function _acceptCrossChainOffer(bytes32 offerId) internal { + if (offers[offerId].sender == address(0)) { + revert OfferDoesNotExist(); } + Offer offer = offers[offerId]; if (offer.expiration <= block.timestamp) { revert OfferHasExpired(); } + // @dev Cannot accept an offer if it's not OPEN if (offer.state != OfferState.OPEN) { revert InvalidOfferState(); } - _offers[offerId].state = OfferState.ACCEPTED; + // TODO Try if we can just change the variable + offers[offerId].state = OfferState.ACCEPTED; } - function _executeOffer(string calldata offerId) internal { - if (_offers[offerId].sender == address(0)) { + function _executeCrossChainOffer(string calldata offerId) internal { + if (offers[offerId].sender == address(0)) { revert OfferDoesNotExist(); } - Offer offer = _offers[offerId]; + Offer offer = offers[offerId]; if (offer.expiration <= block.timestamp) { revert OfferHasExpired(); @@ -77,6 +128,20 @@ abstract contract EchoState { revert InvalidOfferState(); } - delete _offers[offerId]; + delete offers[offerId]; + } + + modifier offerNotExpired(uint64 expiration) { + if (expiration <= block.timestamp) { + revert OfferHasExpired(); + } + _; + } + + modifier offerNotState(uint64 expiration) { + if (expiration <= block.timestamp) { + revert OfferHasExpired(); + } + _; } } diff --git a/src/Handler.sol b/src/Handler.sol deleted file mode 100644 index 1d304a6..0000000 --- a/src/Handler.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "forge-std/interfaces/IERC721.sol"; - -error LengthMismatch(); - -abstract contract Handler { - function _transferERC721(address collectionAddress, uint256 id, address from, address to) internal { - IERC721 collection = IERC721(collectionAddress); - collection.safeTransferFrom(from, to, id); - } - - function _transferTokens(address[] memory collections, uint256[] memory ids, address from, address to) internal { - if (collections.length != ids.length) revert LengthMismatch(); - uint256 length = collections.length; - for (uint256 i = 0; i < length;) { - _transferERC721(collections[i], ids[i], from, to); - unchecked { - i++; - } - } - } -} diff --git a/src/MessageValidator.sol b/src/MessageValidator.sol index 6e99422..29f1b8e 100644 --- a/src/MessageValidator.sol +++ b/src/MessageValidator.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/wormhole/WormholeData.sol"; - error InvalidMessage(); abstract contract MessageValidator { diff --git a/src/Signer.sol b/src/Signer.sol deleted file mode 100644 index db61a5a..0000000 --- a/src/Signer.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "contracts/Handler.sol"; -import "solady/src/utils/ECDSA.sol"; -import "solady/src/utils/EIP712.sol"; -import "solmate/utils/ReentrancyGuard.sol"; - -error InvalidSignature(); -error InvalidSigner(); - -struct Trade { - string id; - address creator; - address counterparty; - uint256 expiresAt; - address[] creatorCollections; - uint256[] creatorIds; - address[] counterpartyCollections; - uint256[] counterpartyIds; -} - -struct Signature { - uint8 v; - bytes32 r; - bytes32 s; -} - -abstract contract Signer is EIP712 { - using ECDSA for bytes32; - using ECDSA for bytes; - - bytes32 private immutable TRADE_TYPEHASH = keccak256( - "Trade(string id,address creator,address counterparty,uint256 expiresAt,address[] creatorCollections,uint256[] creatorIds,address[] counterpartyCollections,uint256[] counterpartyIds)" - ); - - bytes32 private immutable SIGNATURE_TYPEHASH = keccak256("Signature(uint8 v,bytes32 r,bytes32 s)"); - - function _domainNameAndVersion() internal pure override returns (string memory name, string memory version) { - name = "Echo"; - version = "1"; - } - - function hashTypedData(bytes32 structHash) external view returns (bytes32) { - return _hashTypedData(structHash); - } - - function domainSeparator() external view returns (bytes32) { - return _domainSeparator(); - } - - function _validateTrade(Signature calldata signatureData, Trade calldata trade) internal view { - bytes32 structHash = keccak256( - abi.encode( - TRADE_TYPEHASH, - keccak256(bytes(trade.id)), - trade.creator, - trade.counterparty, - trade.expiresAt, - keccak256(abi.encodePacked(trade.creatorCollections)), // address[] - keccak256(abi.encodePacked(trade.creatorIds)), // uint256[] - keccak256(abi.encodePacked(trade.counterpartyCollections)), // address[] - keccak256(abi.encodePacked(trade.counterpartyIds)) // uint256[] - ) - ); - bytes32 hash = keccak256(abi.encodePacked("\x19\x01", this.domainSeparator(), structHash)); - if (ECDSA.recover(hash, signatureData.v, signatureData.r, signatureData.s) != trade.counterparty) { - revert InvalidSignature(); - } - } - - function _validateSignature(uint8 v, bytes32 r, bytes32 s, Signature calldata signatureData, address signer) - internal - view - { - bytes32 structHash = - keccak256(abi.encode(SIGNATURE_TYPEHASH, signatureData.v, signatureData.r, signatureData.s)); - bytes32 hash = keccak256(abi.encodePacked("\x19\x01", this.domainSeparator(), structHash)); - if (ECDSA.recover(hash, v, r, s) != signer) revert InvalidSigner(); - } -} diff --git a/src/TestEcho.sol b/src/TestEcho.sol deleted file mode 100644 index 72b8063..0000000 --- a/src/TestEcho.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "contracts/Echo.sol"; - -// @dev Contract for development purposes only -contract TestEcho is Echo { - constructor(address owner, address signer) Echo(owner, signer) {} - - // @dev Test emission - function mockTradeExecution(string calldata tradeId) external { - // Add trade to list to avoid replay and duplicates - trades[tradeId] = true; - emit TradeExecuted(tradeId); - } - - // @dev Test signer signature - function executeTrade(uint8 v, bytes32 r, bytes32 s, Signature calldata signatureData) - external - payable - nonReentrant - notPaused - { - _validateSignature(v, r, s, signatureData, signer); - emit TradeExecuted("test"); - } -} diff --git a/src/escrow/EscrowHandler.sol b/src/escrow/EscrowHandler.sol index e3d542f..076d9dc 100644 --- a/src/escrow/EscrowHandler.sol +++ b/src/escrow/EscrowHandler.sol @@ -6,7 +6,7 @@ import "contracts/types/OfferItems.sol"; abstract contract EscrowHandler is ERC721TokenReceiver { function _transferERC721(address collectionAddress, uint256 id, address from, address to) internal { - IERC721 collection = IERC721(collectionAddress); + ERC721 collection = ERC721(collectionAddress); collection.safeTransferFrom(from, to, id); } @@ -15,7 +15,7 @@ abstract contract EscrowHandler is ERC721TokenReceiver { function _transferOfferItems(OfferItems calldata offerItems, address from, address to) internal { uint8 length = offerItems.count; for (uint8 i = 0; i < length;) { - _transferERC721(offerItems.items[i].tokenAddress.ethAddress, offerItems.items[i].tokenId, from, to); + _transferERC721(offerItems.items[i].tokenAddress, offerItems.items[i].tokenId, from, to); unchecked { i++; } diff --git a/src/types/Address.sol b/src/types/Address.sol deleted file mode 100644 index d49def8..0000000 --- a/src/types/Address.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -// @dev Struct to represent a multichain address -struct Address { - uint16 chainId; - address ethAddress; -} diff --git a/src/types/Offer.sol b/src/types/Offer.sol index da54341..f0fa062 100644 --- a/src/types/Offer.sol +++ b/src/types/Offer.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/types/Address.sol"; import "contracts/types/OfferItems.sol"; enum OfferState { @@ -10,11 +9,9 @@ enum OfferState { } // @dev Struct representing an on-chain offer -// TODO Should we store the id in the struct as it's already the key in the mapping struct Offer { - string id; - Address sender; - Address receiver; + address sender; + address receiver; OfferItems senderItems; OfferItems receiverItems; uint64 expiration; diff --git a/src/types/OfferItem.sol b/src/types/OfferItem.sol index dbad1b0..f90ad9b 100644 --- a/src/types/OfferItem.sol +++ b/src/types/OfferItem.sol @@ -1,11 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/types/Address.sol"; - // @dev Struct representing an offer item (a token) // @dev We only support ERC721 on EVM chains for now struct OfferItem { - Address tokenAddress; + address tokenAddress; uint256 tokenId; } diff --git a/src/types/OfferItems.sol b/src/types/OfferItems.sol index 6f541be..9a85cc3 100644 --- a/src/types/OfferItems.sol +++ b/src/types/OfferItems.sol @@ -5,6 +5,6 @@ import "contracts/types/OfferItem.sol"; // @dev Struct representing multiple offer items. We store the count for decoding purposes struct OfferItems { - uint8 count; + uint16 chainId; OfferItem[] items; } diff --git a/src/wormhole/Message.sol b/src/wormhole/Message.sol index 0507a5e..27594dc 100644 --- a/src/wormhole/Message.sol +++ b/src/wormhole/Message.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.18; import "contracts/wormhole/BytesLib.sol"; -import "contracts/wormhole/WormholeData.sol"; import "contracts/wormhole/WormholeError.sol"; abstract contract Message { @@ -13,70 +12,70 @@ abstract contract Message { * @param parsedMessage EchoMessage struct with arbitrary HelloWorld message * @return encodedMessage EchoMessage encoded into bytes */ - function _encodeMessage(EchoMessage memory parsedMessage) internal pure returns (bytes memory encodedMessage) { - // Convert message string to bytes so that we can use the .length attribute. - // The length of the arbitrary messages needs to be encoded in the message - // so that the corresponding decode function can decode the message properly. - bytes memory encodedId = abi.encodePacked(parsedMessage.id); - - // return the encoded message - encodedMessage = abi.encodePacked( - parsedMessage.payloadID, - uint16(encodedId.length), - encodedId, - parsedMessage.evmSender, - parsedMessage.evmReceiver, - parsedMessage.evmTokenAddress, - parsedMessage.evmTokenId, - parsedMessage.solSender, - parsedMessage.solReceiver, - parsedMessage.solSenderTokenMint - ); - } - - /** - * @notice Decodes bytes into EchoMessage struct - * @dev Verifies the payloadID - * @param encodedMessage encoded arbitrary Echo message - * @return parsedMessage EchoMessage struct with Solana trade - */ - function _decodeMessage(bytes memory encodedMessage) internal pure returns (EchoMessage memory parsedMessage) { - uint256 index = 0; - - // parse and verify the payloadID - parsedMessage.payloadID = encodedMessage.toUint8(index); - if (parsedMessage.payloadID != 1) { - revert InvalidPayloadId(); - } - index += 1; - - uint256 messageLength = encodedMessage.toUint16(index); - index += 2; - - bytes memory messageBytes = encodedMessage.slice(index, messageLength); - parsedMessage.id = string(messageBytes); - index += messageLength; - - // EVM - parsedMessage.evmSender = encodedMessage.toBytes32(index); - index += 32; - parsedMessage.evmReceiver = encodedMessage.toBytes32(index); - index += 32; - parsedMessage.evmTokenAddress = encodedMessage.toBytes32(index); - index += 32; - parsedMessage.evmTokenId = encodedMessage.toUint64(index); - index += 8; - - // SOL - parsedMessage.solSender = encodedMessage.toBytes32(index); - index += 32; - parsedMessage.solReceiver = encodedMessage.toBytes32(index); - index += 32; - parsedMessage.solSenderTokenMint = encodedMessage.toBytes32(index); - index += 32; - - if (index != encodedMessage.length) { - revert InvalidMessageLength(); - } - } + // function _encodeMessage(EchoMessage memory parsedMessage) internal pure returns (bytes memory encodedMessage) { + // // Convert message string to bytes so that we can use the .length attribute. + // // The length of the arbitrary messages needs to be encoded in the message + // // so that the corresponding decode function can decode the message properly. + // bytes memory encodedId = abi.encodePacked(parsedMessage.id); + // + // // return the encoded message + // encodedMessage = abi.encodePacked( + // parsedMessage.payloadID, + // uint16(encodedId.length), + // encodedId, + // parsedMessage.evmSender, + // parsedMessage.evmReceiver, + // parsedMessage.evmTokenAddress, + // parsedMessage.evmTokenId, + // parsedMessage.solSender, + // parsedMessage.solReceiver, + // parsedMessage.solSenderTokenMint + // ); + // } + // + // /** + // * @notice Decodes bytes into EchoMessage struct + // * @dev Verifies the payloadID + // * @param encodedMessage encoded arbitrary Echo message + // * @return parsedMessage EchoMessage struct with Solana trade + // */ + // function _decodeMessage(bytes memory encodedMessage) internal pure returns (EchoMessage memory parsedMessage) { + // uint256 index = 0; + // + // // parse and verify the payloadID + // parsedMessage.payloadID = encodedMessage.toUint8(index); + // if (parsedMessage.payloadID != 1) { + // revert InvalidPayloadId(); + // } + // index += 1; + // + // uint256 messageLength = encodedMessage.toUint16(index); + // index += 2; + // + // bytes memory messageBytes = encodedMessage.slice(index, messageLength); + // parsedMessage.id = string(messageBytes); + // index += messageLength; + // + // // EVM + // parsedMessage.evmSender = encodedMessage.toBytes32(index); + // index += 32; + // parsedMessage.evmReceiver = encodedMessage.toBytes32(index); + // index += 32; + // parsedMessage.evmTokenAddress = encodedMessage.toBytes32(index); + // index += 32; + // parsedMessage.evmTokenId = encodedMessage.toUint64(index); + // index += 8; + // + // // SOL + // parsedMessage.solSender = encodedMessage.toBytes32(index); + // index += 32; + // parsedMessage.solReceiver = encodedMessage.toBytes32(index); + // index += 32; + // parsedMessage.solSenderTokenMint = encodedMessage.toBytes32(index); + // index += 32; + // + // if (index != encodedMessage.length) { + // revert InvalidMessageLength(); + // } + // } } diff --git a/src/wormhole/MessageTypes.sol b/src/wormhole/MessageTypes.sol new file mode 100644 index 0000000..66604f5 --- /dev/null +++ b/src/wormhole/MessageTypes.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +/** + * Base types for messaging + */ +// @dev Struct representing an offer item (a token) +// @dev We only support ERC721 on EVM chains for now +struct OfferItem { + address tokenAddress; + uint256 tokenId; +} + +// @dev Struct representing multiple offer items. +// @dev We store the count for decoding purposes +struct OfferItems { + uint8 count; + uint16 chainId; + OfferItem[] items; +} + +/** + * Wormhole messages types + */ +struct OfferCreatedMessage { + bytes32 offerId; + address sender; + address receiver; + OfferItems[] senderItems; + OfferItems[] receiverItems; + uint64 expiration; +} + +struct OfferAcceptedMessage { + bytes32 offerId; +} + +struct OfferCancelledMessage { + bytes32 offerId; +} diff --git a/src/wormhole/WormholeData.sol b/src/wormhole/WormholeData.sol deleted file mode 100644 index 0188341..0000000 --- a/src/wormhole/WormholeData.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -struct OfferCreatedMessage { - string offerId; - Address sender; - Address receiver; - OfferItems[] senderItems; - OfferItems[] receiverItems; - uint64 expiration; -} - -struct OfferAcceptedMessage { - string offerId; -} - -struct OfferCancelledMessage { - string offerId; -} diff --git a/src/wormhole/WormholeGovernance.sol b/src/wormhole/WormholeGovernance.sol index b259612..8e8f602 100644 --- a/src/wormhole/WormholeGovernance.sol +++ b/src/wormhole/WormholeGovernance.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.18; import "contracts/wormhole/IWormhole.sol"; import "contracts/wormhole/Message.sol"; -import "contracts/wormhole/WormholeData.sol"; import "contracts/wormhole/WormholeError.sol"; import "contracts/wormhole/WormholeState.sol"; import "solmate/auth/Owned.sol"; @@ -24,77 +23,77 @@ abstract contract WormholeGovernance is Owned, Message, WormholeState { _state.wormholeFinality = wormholeFinality_; } - /** - * @notice Sends an EchoMessage - * @dev batchID is set to 0 to opt out of batching in future Wormhole versions. - * Reverts if: - * - caller doesn't pass enough value to pay the Wormhole network fee - * @param message EchoMessageWithoutPayload to send - * @return messageSequence Wormhole message sequence for this contract - */ - function _sendMessage(EchoMessageWithoutPayload memory message) - internal - hasEnoughWormholeFees - returns (uint64 messageSequence) - { - EchoMessage memory parsedMessage = EchoMessage({ - payloadID: uint8(1), - id: message.id, - evmSender: message.evmSender, - evmReceiver: message.evmReceiver, - evmTokenAddress: message.evmTokenAddress, - evmTokenId: message.evmTokenId, - solSender: message.solSender, - solReceiver: message.solReceiver, - solSenderTokenMint: message.solSenderTokenMint - }); - - bytes memory encodedMessage = _encodeMessage(parsedMessage); - - // Send the Echo message by calling publishMessage on the - // Wormhole core contract and paying the Wormhole protocol fee. - messageSequence = wormhole.publishMessage{value: wormholeFee}( - 0, // batchID - encodedMessage, - _state.wormholeFinality - ); - } - - /** - * @notice Consumes arbitrary Echo messages sent by registered emitters - * @dev The arbitrary message is verified by the Wormhole core endpoint - * `verifyVM`. - * Reverts if: - * - `encodedMessage` is not attested by the Wormhole network - * - `encodedMessage` was sent by an unregistered emitter - * - `encodedMessage` was consumed already - * @param encodedMessage verified Wormhole message containing arbitrary - * @return parsedMessage EchoMessage The parsed message from Wormhole - */ - function receiveMessage(bytes memory encodedMessage) internal returns (EchoMessage memory parsedMessage) { - // call the Wormhole core contract to parse and verify the encodedMessage - (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = - wormholeContract().parseAndVerifyVM(encodedMessage); - - if (!valid) { - // TODO Add reason? - revert FailedParsingAndVerifyingVm(); - } - - if (!_verifyEmitter(wormholeMessage)) { - revert InvalidEmitter(); - } - - parsedMessage = _decodeMessage(wormholeMessage.payload); - - if (isMessageConsumed(wormholeMessage.hash)) { - revert MessageAlreadyConsumed(); - } - _consumeMessage(wormholeMessage.hash); - } + // /** + // * @notice Sends an EchoMessage + // * @dev batchID is set to 0 to opt out of batching in future Wormhole versions. + // * Reverts if: + // * - caller doesn't pass enough value to pay the Wormhole network fee + // * @param message EchoMessageWithoutPayload to send + // * @return messageSequence Wormhole message sequence for this contract + // */ + // function _sendMessage( + // EchoMessageWithoutPayload memory message + // ) internal hasEnoughWormholeFees returns (uint64 messageSequence) { + // EchoMessage memory parsedMessage = EchoMessage({ + // payloadID: uint8(1), + // id: message.id, + // evmSender: message.evmSender, + // evmReceiver: message.evmReceiver, + // evmTokenAddress: message.evmTokenAddress, + // evmTokenId: message.evmTokenId, + // solSender: message.solSender, + // solReceiver: message.solReceiver, + // solSenderTokenMint: message.solSenderTokenMint + // }); + // + // bytes memory encodedMessage = _encodeMessage(parsedMessage); + // + // // Send the Echo message by calling publishMessage on the + // // Wormhole core contract and paying the Wormhole protocol fee. + // messageSequence = wormhole.publishMessage{value: wormholeFee}( + // 0, // batchID + // encodedMessage, + // _state.wormholeFinality + // ); + // } + // + // /** + // * @notice Consumes arbitrary Echo messages sent by registered emitters + // * @dev The arbitrary message is verified by the Wormhole core endpoint + // * `verifyVM`. + // * Reverts if: + // * - `encodedMessage` is not attested by the Wormhole network + // * - `encodedMessage` was sent by an unregistered emitter + // * - `encodedMessage` was consumed already + // * @param encodedMessage verified Wormhole message containing arbitrary + // * @return parsedMessage EchoMessage The parsed message from Wormhole + // */ + // function receiveMessage( + // bytes memory encodedMessage + // ) internal returns (EchoMessage memory parsedMessage) { + // // call the Wormhole core contract to parse and verify the encodedMessage + // (IWormhole.VM memory wormholeMessage, bool valid, string memory reason) = wormholeContract() + // .parseAndVerifyVM(encodedMessage); + // + // if (!valid) { + // // TODO Add reason? + // revert FailedParsingAndVerifyingVm(); + // } + // + // if (!_verifyEmitter(wormholeMessage)) { + // revert InvalidEmitter(); + // } + // + // parsedMessage = _decodeMessage(wormholeMessage.payload); + // + // if (isMessageConsumed(wormholeMessage.hash)) { + // revert MessageAlreadyConsumed(); + // } + // _consumeMessage(wormholeMessage.hash); + // } modifier hasEnoughWormholeFees() { - IWormhole wormhole = wormholeContract(); + IWormhole wormhole = this.wormholeContract(); uint256 wormholeFee = wormhole.messageFee(); if (msg.value != wormholeFee) { diff --git a/src/wormhole/WormholeState.sol b/src/wormhole/WormholeState.sol index 9074b47..fbecf44 100644 --- a/src/wormhole/WormholeState.sol +++ b/src/wormhole/WormholeState.sol @@ -8,7 +8,7 @@ import "solmate/auth/Owned.sol"; struct State { // address of the Wormhole contract on this chain address wormhole; - // Need to store the chain ID as it might differ from the real id + // @dev Need to store the chain ID as it might differ from the real id // I.e. Ethereum is chainId = 2 for Wormhole because Solana is chainId = 1 uint16 chainId; /** diff --git a/test/Admin.t.sol b/test/Admin.t.sol index 1040b4e..5f9ab51 100644 --- a/test/Admin.t.sol +++ b/test/Admin.t.sol @@ -2,22 +2,10 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.t.sol"; +import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract AdminTest is BaseTest { - function testCannotChangeFeesIfNotOwner() public { - vm.prank(account1); - vm.expectRevert("UNAUTHORIZED"); - echo.setFees(0 ether); - } - - function testCanChangeFeesIfOwner() public { - vm.prank(owner); - echo.setFees(0.005 ether); - assertEq(echo.tradingFee(), 0.005 ether); - } - function testCannotPauseIfNotOwner() public { vm.prank(account1); vm.expectRevert("UNAUTHORIZED"); diff --git a/test/Approval.t.sol b/test/Approval.t.sol index d37f4f0..84ad42f 100644 --- a/test/Approval.t.sol +++ b/test/Approval.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.t.sol"; +import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract ApprovalTest is BaseTest { diff --git a/test/Banker.t.sol b/test/Banker.t.sol new file mode 100644 index 0000000..a97007e --- /dev/null +++ b/test/Banker.t.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "./BaseTest.t.sol"; +import "./mock/Mocked721.sol"; +import "forge-std/Test.sol"; + +contract BankerTest is BaseTest { + function testCannotChangeFeesIfNotOwner() public { + vm.prank(account1); + vm.expectRevert("UNAUTHORIZED"); + echo.setFees(0 ether); + } + + function testCanChangeFeesIfOwner() public { + vm.prank(owner); + echo.setFees(0.005 ether); + assertEq(echo.tradingFee(), 0.005 ether); + } + + function testCannotWithdrawIfNotOwner() public { + // Set fees + vm.prank(owner); + echo.setFees(0.005 ether); + + creator721Collections.push(apeAddress); + creator721Ids.push(ape1Id); + counterparty721Collections.push(birdAddress); + counterparty721Ids.push(bird1Id); + _executeMockTrade("test", account1, account2, 0.005 ether); + + vm.prank(account1); + vm.expectRevert("UNAUTHORIZED"); + echo.withdraw(account1); + } + + function testCanWithdrawToSelfIfOwner() public { + // Set fees + vm.prank(owner); + echo.setFees(0.005 ether); + + creator721Collections.push(apeAddress); + creator721Ids.push(ape1Id); + counterparty721Collections.push(birdAddress); + counterparty721Ids.push(bird1Id); + _executeMockTrade("test", account1, account2, 0.005 ether); + + assertEq(address(echo).balance, 0.005 ether); + vm.prank(owner); + echo.withdraw(owner); + assertEq(owner.balance, 0.005 ether); + assertEq(address(echo).balance, 0); + } + + function testCanWithdrawToOtherAccountIfOwner() public { + // Set fees + vm.prank(owner); + echo.setFees(0.005 ether); + + creator721Collections.push(apeAddress); + creator721Ids.push(ape1Id); + counterparty721Collections.push(birdAddress); + counterparty721Ids.push(bird1Id); + _executeMockTrade("test", account1, account2, 0.005 ether); + + vm.prank(owner); + echo.withdraw(account3); + assertEq(account3.balance, 100 ether + 0.005 ether); + assertEq(address(echo).balance, 0); + } + + function testCannotWithdrawToContractIfOwner() public { + // Set fees + vm.prank(owner); + echo.setFees(0.005 ether); + + creator721Collections.push(apeAddress); + creator721Ids.push(ape1Id); + counterparty721Collections.push(birdAddress); + counterparty721Ids.push(bird1Id); + _executeMockTrade("test", account1, account2, 0.005 ether); + + vm.prank(owner); + vm.expectRevert(WithdrawFailed.selector); + echo.withdraw(address(echo)); + assertEq(account3.balance, 100 ether); + assertEq(address(echo).balance, 0.005 ether); + } +} diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index 57712c4..d0ff33e 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -1,19 +1,25 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; -import "./mock/Mocked721.t.sol"; -import "./mock/MockHandler.t.sol"; -import "./utils/Constants.sol"; +import "./mock/Mocked721.sol"; +import "./mock/MockHandler.sol"; +import "./mock/WormholeSimulator.sol"; +import "contracts/EchoCrossChain.sol"; +import "contracts/wormhole/IWormhole.sol"; import "forge-std/Test.sol"; -import "src/Echo.sol"; -abstract contract BaseTest is Test, Constants { +abstract contract BaseTest is Test { // Exclude from coverage report function test() public {} - event TradeExecuted(string id); + // guardian private key for simulated signing of Wormhole messages + uint256 guardianSigner; - Echo public echo; + // contract instances + IWormhole wormhole; + WormholeSimulator wormholeSimulator; + + EchoCrossChain public echo; // To test internal function as it's impossible to reach the code // from echo (echo also checks for length) MockedHandler public handler; @@ -57,7 +63,28 @@ abstract contract BaseTest is Test, Constants { vm.deal(account3, 100 ether); vm.deal(account4, 100 ether); - echo = new Echo({owner: owner, signer: signer}); + /* Initialize wormhole */ + // verify that we're using the correct fork (AVAX mainnet in this case) + require(block.chainid == vm.envUint("TESTING_AVAX_FORK_CHAINID"), "wrong evm"); + + // this will be used to sign Wormhole messages + guardianSigner = uint256(vm.envBytes32("TESTING_DEVNET_GUARDIAN")); + + // we may need to interact with Wormhole throughout the test + wormhole = IWormhole(vm.envAddress("TESTING_AVAX_WORMHOLE_ADDRESS")); + + // set up Wormhole using Wormhole existing on AVAX mainnet + wormholeSimulator = new SigningWormholeSimulator(wormhole, guardianSigner); + + // verify Wormhole state from fork + require(wormhole.chainId() == uint16(vm.envUint("TESTING_AVAX_WORMHOLE_CHAINID")), "wrong chainId"); + require(wormhole.messageFee() == vm.envUint("TESTING_AVAX_WORMHOLE_MESSAGE_FEE"), "wrong messageFee"); + require( + wormhole.getCurrentGuardianSetIndex() == uint32(vm.envUint("TESTING_AVAX_WORMHOLE_GUARDIAN_SET_INDEX")), + "wrong guardian set index" + ); + + echo = new EchoCrossChain(address(owner), address(wormhole), wormhole.chainId(), uint8(1)); handler = new MockedHandler(); apes = new Mocked721("Apes", "APE"); @@ -91,65 +118,26 @@ abstract contract BaseTest is Test, Constants { in6hours = block.timestamp + (60 * 60 * 6); } - // @dev Sign the trade with private key - function _signTrade(Trade memory trade, uint256 privateKey) internal view returns (uint8 v, bytes32 r, bytes32 s) { - bytes32 hashStruct = keccak256( - abi.encode( - TRADE_TYPEHASH, - keccak256(bytes(trade.id)), - trade.creator, - trade.counterparty, - trade.expiresAt, - keccak256(abi.encodePacked(trade.creatorCollections)), // address[] - keccak256(abi.encodePacked(trade.creatorIds)), // uint256[] - keccak256(abi.encodePacked(trade.counterpartyCollections)), // address[] - keccak256(abi.encodePacked(trade.counterpartyIds)) // uint256[] - ) - ); - - bytes32 digest = keccak256(abi.encodePacked("\x19\x01", echo.domainSeparator(), hashStruct)); - (v, r, s) = vm.sign(privateKey, digest); - } - - // @dev Sign the signature with the private key. This is simulating the backend signing - function _signSignature(Signature memory signature, uint256 privateKey) - internal - view - returns (uint8 v, bytes32 r, bytes32 s) - { - bytes32 hashStruct = keccak256(abi.encode(SIGNATURE_TYPEHASH, signature.v, signature.r, signature.s)); - bytes32 digest = keccak256(abi.encodePacked("\x19\x01", echo.domainSeparator(), hashStruct)); - (v, r, s) = vm.sign(privateKey, digest); - } - - // @dev Util function to generate the backend signature of the trade, returns all the data to execute the trade - function _prepareSignature(Trade memory trade, uint256 counterpartyPrivateKey, uint256 _signerPrivateKey) - internal - view - returns (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) - { - (uint8 v, bytes32 r, bytes32 s) = _signTrade(trade, counterpartyPrivateKey); - signature = Signature({v: v, r: r, s: s}); - (vSigner, rSigner, sSigner) = _signSignature(signature, _signerPrivateKey); - } - // @dev Method to execute a mock trade with predefined values // @dev Do not use this method if you expect a revert as the way Foundry is built, it won't catch the revert function _executeMockTrade(string memory id, address creator, address counter, uint256 fees) internal { - Trade memory trade = Trade({ - id: id, - creator: creator, - counterparty: counter, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - (uint8 v, bytes32 r, bytes32 s) = _signTrade(trade, account2PrivateKey); - Signature memory signature = Signature({v: v, r: r, s: s}); - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner) = _signSignature(signature, signerPrivateKey); - vm.prank(creator); - echo.executeTrade{value: fees}(vSigner, rSigner, sSigner, signature, trade); + // Trade memory trade = Trade({ + // id: id, + // creator: creator, + // counterparty: counter, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // (uint8 v, bytes32 r, bytes32 s) = _signTrade(trade, account2PrivateKey); + // Signature memory signature = Signature({v: v, r: r, s: s}); + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner) = _signSignature( + // signature, + // signerPrivateKey + // ); + // vm.prank(creator); + // echo.executeTrade{value: fees}(vSigner, rSigner, sSigner, signature, trade); } } diff --git a/test/Expiration.t.sol b/test/Expiration.t.sol index a4e29c4..6c6e6fb 100644 --- a/test/Expiration.t.sol +++ b/test/Expiration.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.t.sol"; +import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract ExpirationTest is BaseTest { diff --git a/test/Fees.t.sol b/test/Fees.t.sol index 4ef8840..4442deb 100644 --- a/test/Fees.t.sol +++ b/test/Fees.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.t.sol"; +import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract FeesTest is BaseTest { diff --git a/test/MockTradeExecution.t.sol b/test/MockTradeExecution.t.sol deleted file mode 100644 index e20a66b..0000000 --- a/test/MockTradeExecution.t.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "./mock/Mocked721.t.sol"; -import "./mock/MockHandler.t.sol"; -import "./utils/Constants.sol"; -import "forge-std/Test.sol"; -import "src/TestEcho.sol"; - -// @dev Only used to test the TestEcho contract which is a simple contract to test signatures -contract MockTradeExecution is Test, Constants { - TestEcho public echo; - - event TradeExecuted(string id); - - uint256 public constant ownerPrivateKey = 0xB0B; - address public owner; - - function setUp() public { - owner = vm.addr(ownerPrivateKey); - echo = new TestEcho({owner: owner, signer: owner}); - } - - // @dev Sign the signature with the private key. This is simulating the backend signing - function _signSignature(Signature memory signature, uint256 privateKey) - internal - view - returns (uint8 v, bytes32 r, bytes32 s) - { - bytes32 hashStruct = keccak256(abi.encode(SIGNATURE_TYPEHASH, signature.v, signature.r, signature.s)); - bytes32 digest = keccak256(abi.encodePacked("\x19\x01", echo.domainSeparator(), hashStruct)); - (v, r, s) = vm.sign(privateKey, digest); - } - - function testTradeEmission() public { - vm.prank(owner); - vm.expectEmit(true, true, true, true); - emit TradeExecuted("test"); - echo.mockTradeExecution("test"); - } - - function testSigner() public { - (uint8 v, bytes32 r, bytes32 s) = _signSignature(mockSignature, ownerPrivateKey); - - vm.prank(owner); - vm.expectEmit(true, true, true, true); - emit TradeExecuted("test"); - echo.executeTrade(v, r, s, mockSignature); - } - - function testWrongSigner() public { - (uint8 v, bytes32 r, bytes32 s) = _signSignature(mockSignature, 0xA11CE); - - vm.prank(owner); - vm.expectRevert(InvalidSigner.selector); - echo.executeTrade(v, r, s, mockSignature); - } -} diff --git a/test/Ownership.t.sol b/test/Ownership.t.sol index 51b14ae..760ec6f 100644 --- a/test/Ownership.t.sol +++ b/test/Ownership.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.t.sol"; +import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract OwnershipTest is BaseTest { diff --git a/test/Signature.t.sol b/test/Signature.t.sol index 49b73a1..9f7d7fd 100644 --- a/test/Signature.t.sol +++ b/test/Signature.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.t.sol"; +import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract SignatureTest is BaseTest { diff --git a/test/TestBridge.t.sol b/test/TestBridge.t.sol index b75ad56..26d1076 100644 --- a/test/TestBridge.t.sol +++ b/test/TestBridge.t.sol @@ -1,5 +1,5 @@ -//// SPDX-License-Identifier: Apache 2 -//pragma solidity ^0.8.18; +// SPDX-License-Identifier: Apache 2 +pragma solidity ^0.8.18; // //import "./utils/WormholeSimulator.sol"; //import "./utils/EchoCrossChainTest.sol"; diff --git a/test/Trade721.t.sol b/test/Trade721.t.sol index 45538b1..87298b7 100644 --- a/test/Trade721.t.sol +++ b/test/Trade721.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.t.sol"; +import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract Trade721Test is BaseTest { diff --git a/test/mock/MockHandler.sol b/test/mock/MockHandler.sol new file mode 100644 index 0000000..0a7c2e1 --- /dev/null +++ b/test/mock/MockHandler.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "contracts/escrow/EscrowHandler.sol"; + +contract MockedHandler is EscrowHandler {} diff --git a/test/mock/MockHandler.t.sol b/test/mock/MockHandler.t.sol deleted file mode 100644 index 18fe2e5..0000000 --- a/test/mock/MockHandler.t.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "src/Handler.sol"; - -contract MockedHandler is Handler { - function transferTokens(address[] memory collections, uint256[] memory ids, address from, address to) external { - _transferTokens(collections, ids, from, to); - } -} diff --git a/test/utils/MockWormhole.sol b/test/mock/MockWormhole.sol similarity index 100% rename from test/utils/MockWormhole.sol rename to test/mock/MockWormhole.sol diff --git a/test/mock/Mocked721.t.sol b/test/mock/Mocked721.sol similarity index 100% rename from test/mock/Mocked721.t.sol rename to test/mock/Mocked721.sol diff --git a/test/utils/WormholeSimulator.sol b/test/mock/WormholeSimulator.sol similarity index 99% rename from test/utils/WormholeSimulator.sol rename to test/mock/WormholeSimulator.sol index 692209b..00227a6 100644 --- a/test/utils/WormholeSimulator.sol +++ b/test/mock/WormholeSimulator.sol @@ -1,12 +1,11 @@ // SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.18; -import "forge-std/Vm.sol"; -import "forge-std/console.sol"; - -import "contracts/wormhole/IWormhole.sol"; import "./MockWormhole.sol"; import "contracts/wormhole/BytesLib.sol"; +import "contracts/wormhole/IWormhole.sol"; +import "forge-std/Vm.sol"; +import "forge-std/console.sol"; /** * @notice These are the common parts for the signing and the non signing wormhole simulators. diff --git a/test/utils/Constants.sol b/test/utils/Constants.sol deleted file mode 100644 index efeef3f..0000000 --- a/test/utils/Constants.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "src/Signer.sol"; - -// @dev Constants file for testing since we use private immutable on the main contract to save gas. -// Make sure this file is in sync with Signer.sol for the proper type hashes. - -bytes32 constant TRADE_TYPEHASH = keccak256( - "Trade(string id,address creator,address counterparty,uint256 expiresAt,address[] creatorCollections,uint256[] creatorIds,address[] counterpartyCollections,uint256[] counterpartyIds)" -); -bytes32 constant SIGNATURE_TYPEHASH = keccak256("Signature(uint8 v,bytes32 r,bytes32 s)"); - -abstract contract Constants { - Signature public mockSignature = Signature({ - v: 28, - r: 0x1ac3cd5c3835114c9bfb58984f010a0036d805934ec30918463de615cedffe7b, - s: 0x02332013ae020ab4d85c6ae841a11ba4564cb9f3275afe8adde07c80ab14ae78 - }); -} diff --git a/test/utils/EchoCrossChainTest.sol b/test/utils/EchoCrossChainTest.sol deleted file mode 100644 index 1580741..0000000 --- a/test/utils/EchoCrossChainTest.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "contracts/EchoCrossChain.sol"; -import "contracts/wormhole/WormholeData.sol"; - -contract EchoCrossChainTest is EchoCrossChain { - constructor(address owner, address wormhole, uint16 chainId, uint8 wormholeFinality) - EchoCrossChain(owner, wormhole, chainId, wormholeFinality) - {} - - function sendMessage(EchoMessageWithoutPayload memory message) public payable returns (uint64 messageSequence) { - return _sendMessage(message); - } - - function receiveMessage(bytes memory encodedMessage) public returns (EchoMessage memory parsedMessage) { - return _receiveMessage(encodedMessage); - } -} From e0d9b674dea3b54877cf8a3d9ec885dc99e0fe5a Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Tue, 7 May 2024 16:12:05 -0400 Subject: [PATCH 08/28] compiling works --- src/EchoState.sol | 21 +- src/escrow/EscrowHandler.sol | 4 +- test/Admin.t.sol | 18 -- test/Approval.t.sol | 174 ++++++------- test/Expiration.t.sol | 94 +++---- test/Fees.t.sol | 124 ++++----- test/Handler.t.sol | 46 ++-- test/Ownership.t.sol | 160 ++++++------ test/Signature.t.sol | 144 ----------- test/Trade721.t.sol | 266 +++++++++---------- test/WrongAssets.t.sol | 484 +++++++++++++++++------------------ 11 files changed, 683 insertions(+), 852 deletions(-) delete mode 100644 test/Signature.t.sol diff --git a/src/EchoState.sol b/src/EchoState.sol index 4b073bd..c92ff88 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -16,23 +16,23 @@ abstract contract EchoState { /** * Utils */ - function _generateOfferId(Offer calldata offer) internal returns (bytes32 offerId) { + function _generateOfferId(Offer calldata offer) internal pure returns (bytes32 offerId) { // TODO Validate this behaviour offerId = keccak256( abi.encode( offer.sender, offer.receiver, offer.senderItems.chainId, - keccak256(abi.encodePacked(offer.senderItems.items)), // OfferItem[] + keccak256(abi.encode(offer.senderItems.items)), // OfferItem[] offer.receiverItems.chainId, - keccak256(abi.encodePacked(offer.receiverItems.items)), // OfferItem[] + keccak256(abi.encode(offer.receiverItems.items)), // OfferItem[] offer.expiration ) ); } // @dev Internal function to check that offer data is valid for creation - function _validateOffer(bytes32 offerId, Offer calldata offer) internal offerNotExpired(offer.expiration) { + function _validateOffer(bytes32 offerId, Offer calldata offer) internal view offerNotExpired(offer.expiration) { if (offers[offerId].sender != address(0)) { revert OfferAlreadyExist(); } @@ -100,7 +100,7 @@ abstract contract EchoState { if (offers[offerId].sender == address(0)) { revert OfferDoesNotExist(); } - Offer offer = offers[offerId]; + Offer memory offer = offers[offerId]; if (offer.expiration <= block.timestamp) { revert OfferHasExpired(); @@ -114,11 +114,11 @@ abstract contract EchoState { offers[offerId].state = OfferState.ACCEPTED; } - function _executeCrossChainOffer(string calldata offerId) internal { + function _executeCrossChainOffer(bytes32 offerId) internal { if (offers[offerId].sender == address(0)) { revert OfferDoesNotExist(); } - Offer offer = offers[offerId]; + Offer memory offer = offers[offerId]; if (offer.expiration <= block.timestamp) { revert OfferHasExpired(); @@ -137,11 +137,4 @@ abstract contract EchoState { } _; } - - modifier offerNotState(uint64 expiration) { - if (expiration <= block.timestamp) { - revert OfferHasExpired(); - } - _; - } } diff --git a/src/escrow/EscrowHandler.sol b/src/escrow/EscrowHandler.sol index 076d9dc..8c33799 100644 --- a/src/escrow/EscrowHandler.sol +++ b/src/escrow/EscrowHandler.sol @@ -13,8 +13,8 @@ abstract contract EscrowHandler is ERC721TokenReceiver { // TODO add check for chain or size 0? // @dev function to transfer items from an offer type function _transferOfferItems(OfferItems calldata offerItems, address from, address to) internal { - uint8 length = offerItems.count; - for (uint8 i = 0; i < length;) { + uint256 length = offerItems.items.length; + for (uint256 i = 0; i < length;) { _transferERC721(offerItems.items[i].tokenAddress, offerItems.items[i].tokenId, from, to); unchecked { i++; diff --git a/test/Admin.t.sol b/test/Admin.t.sol index 5f9ab51..d072e61 100644 --- a/test/Admin.t.sol +++ b/test/Admin.t.sol @@ -93,22 +93,4 @@ contract AdminTest is BaseTest { assertEq(account3.balance, 100 ether); assertEq(address(echo).balance, 0.005 ether); } - - function testCannotChangeSignerIfNotOwner() public { - vm.prank(account1); - vm.expectRevert("UNAUTHORIZED"); - echo.setSigner(address(0xB0B)); - } - - function testCannotChangeSignerToAddress0() public { - vm.prank(owner); - vm.expectRevert(InvalidAddress.selector); - echo.setSigner(address(0)); - } - - function testCanChangeSignerIfOwner() public { - vm.prank(owner); - echo.setSigner(address(0xB0B)); - assertEq(echo.signer(), address(0xB0B)); - } } diff --git a/test/Approval.t.sol b/test/Approval.t.sol index 84ad42f..3ff1b01 100644 --- a/test/Approval.t.sol +++ b/test/Approval.t.sol @@ -6,91 +6,91 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract ApprovalTest is BaseTest { - // Creator has not approved its apes - function testCannotExecuteTradeIfCreatorDidNotApprove() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape3Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account3, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account3); - vm.expectRevert(bytes("NOT_AUTHORIZED")); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - /// Counterparty has not approved its birds - function testCannotExecuteTradeIfCounterpartyDidNotApprove() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - vm.startPrank(account2); - birds.setApprovalForAll(address(echo), false); - vm.stopPrank(); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(bytes("NOT_AUTHORIZED")); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - /// Succeeds when both creator and counterparty have approved their assets - function testSucceedsWhenApproved() public { - // Assets are in original state - assertEq(apes.ownerOf(1), account1); - assertEq(birds.ownerOf(1), account2); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectEmit(true, true, true, true); - emit TradeExecuted("test"); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are now swapped - assertEq(apes.ownerOf(1), account2); - assertEq(birds.ownerOf(1), account1); - } +// Creator has not approved its apes +// function testCannotExecuteTradeIfCreatorDidNotApprove() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape3Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account3, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account3); +// vm.expectRevert(bytes("NOT_AUTHORIZED")); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } +// +// /// Counterparty has not approved its birds +// function testCannotExecuteTradeIfCounterpartyDidNotApprove() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// vm.startPrank(account2); +// birds.setApprovalForAll(address(echo), false); +// vm.stopPrank(); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(bytes("NOT_AUTHORIZED")); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } +// +// /// Succeeds when both creator and counterparty have approved their assets +// function testSucceedsWhenApproved() public { +// // Assets are in original state +// assertEq(apes.ownerOf(1), account1); +// assertEq(birds.ownerOf(1), account2); +// +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectEmit(true, true, true, true); +// emit TradeExecuted("test"); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are now swapped +// assertEq(apes.ownerOf(1), account2); +// assertEq(birds.ownerOf(1), account1); +// } } diff --git a/test/Expiration.t.sol b/test/Expiration.t.sol index 6c6e6fb..53f2c1f 100644 --- a/test/Expiration.t.sol +++ b/test/Expiration.t.sol @@ -6,51 +6,51 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract ExpirationTest is BaseTest { - function testExpiresAtCurrentBlock() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - uint256 expired = block.timestamp; - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: expired, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(TradeHasExpired.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - function testExpiresBeforeCurrentBlock() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - uint256 expired = block.timestamp - 1; - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: expired, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(TradeHasExpired.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } +// function testExpiresAtCurrentBlock() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// uint256 expired = block.timestamp; +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: expired, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(TradeHasExpired.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } +// +// function testExpiresBeforeCurrentBlock() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// uint256 expired = block.timestamp - 1; +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: expired, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(TradeHasExpired.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } } diff --git a/test/Fees.t.sol b/test/Fees.t.sol index 4442deb..59f2de6 100644 --- a/test/Fees.t.sol +++ b/test/Fees.t.sol @@ -6,66 +6,66 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract FeesTest is BaseTest { - function testRevertsWithoutFunds() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(InvalidPayment.selector); - // 0 ether - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - vm.prank(account1); - vm.expectRevert(InvalidPayment.selector); - // Not enough ether - echo.executeTrade{value: 0.004 ether}(vSigner, rSigner, sSigner, signature, trade); - } - - function testSucceedsWithFunds() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - echo.executeTrade{value: 0.005 ether}(vSigner, rSigner, sSigner, signature, trade); - assertEq(address(echo).balance, 0.005 ether); - assertEq(account1.balance, 100 ether - 0.005 ether); - } +// function testRevertsWithoutFunds() public { +// // Set fees +// vm.prank(owner); +// echo.setFees(0.005 ether); +// +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(InvalidPayment.selector); +// // 0 ether +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// vm.prank(account1); +// vm.expectRevert(InvalidPayment.selector); +// // Not enough ether +// echo.executeTrade{value: 0.004 ether}(vSigner, rSigner, sSigner, signature, trade); +// } +// +// function testSucceedsWithFunds() public { +// // Set fees +// vm.prank(owner); +// echo.setFees(0.005 ether); +// +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// echo.executeTrade{value: 0.005 ether}(vSigner, rSigner, sSigner, signature, trade); +// assertEq(address(echo).balance, 0.005 ether); +// assertEq(account1.balance, 100 ether - 0.005 ether); +// } } diff --git a/test/Handler.t.sol b/test/Handler.t.sol index 1b6dc99..50c1457 100644 --- a/test/Handler.t.sol +++ b/test/Handler.t.sol @@ -5,27 +5,27 @@ import "./BaseTest.t.sol"; import "forge-std/Test.sol"; contract HandlerTest is BaseTest { - function testIdsLonger() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - creator721Ids.push(ape2Id); - - vm.expectRevert(LengthMismatch.selector); - handler.transferTokens(creator721Collections, creator721Ids, account1, account2); - - // Assets are not swapped - assertEq(apes.ownerOf(1), account1); - assertEq(apes.ownerOf(2), account1); - } - - function testCollectionsLonger() public { - creator721Collections.push(apeAddress); - creator721Collections.push(apeAddress); - creator721Ids.push(ape2Id); - - vm.expectRevert(LengthMismatch.selector); - handler.transferTokens(creator721Collections, creator721Ids, account1, account2); - // Assets are not swapped - assertEq(apes.ownerOf(2), account1); - } +// function testIdsLonger() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// creator721Ids.push(ape2Id); +// +// vm.expectRevert(LengthMismatch.selector); +// handler.transferTokens(creator721Collections, creator721Ids, account1, account2); +// +// // Assets are not swapped +// assertEq(apes.ownerOf(1), account1); +// assertEq(apes.ownerOf(2), account1); +// } +// +// function testCollectionsLonger() public { +// creator721Collections.push(apeAddress); +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape2Id); +// +// vm.expectRevert(LengthMismatch.selector); +// handler.transferTokens(creator721Collections, creator721Ids, account1, account2); +// // Assets are not swapped +// assertEq(apes.ownerOf(2), account1); +// } } diff --git a/test/Ownership.t.sol b/test/Ownership.t.sol index 760ec6f..4b33665 100644 --- a/test/Ownership.t.sol +++ b/test/Ownership.t.sol @@ -6,84 +6,84 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract OwnershipTest is BaseTest { - // Sender is not creator - function testCannotExecuteTradeIfNotCreator() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // Counterparty - vm.prank(account2); - vm.expectRevert(InvalidCreator.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Random account - vm.prank(account3); - vm.expectRevert(InvalidCreator.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - // Creator is not owner - function testCannotExecuteTradeIfCreatorNotOwner() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account3, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account3); - vm.expectRevert(bytes("WRONG_FROM")); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - // TODO Should be the same error message as the other? - // Counterparty is not owner - function testCannotExecuteTradeIfCounterpartyNotOwner() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird3Id); - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(bytes("WRONG_FROM")); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } +// // Sender is not creator +// function testCannotExecuteTradeIfNotCreator() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// // Counterparty +// vm.prank(account2); +// vm.expectRevert(InvalidCreator.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Random account +// vm.prank(account3); +// vm.expectRevert(InvalidCreator.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } +// +// // Creator is not owner +// function testCannotExecuteTradeIfCreatorNotOwner() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account3, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account3); +// vm.expectRevert(bytes("WRONG_FROM")); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } +// +// // TODO Should be the same error message as the other? +// // Counterparty is not owner +// function testCannotExecuteTradeIfCounterpartyNotOwner() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird3Id); +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(bytes("WRONG_FROM")); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } } diff --git a/test/Signature.t.sol b/test/Signature.t.sol deleted file mode 100644 index 9f7d7fd..0000000 --- a/test/Signature.t.sol +++ /dev/null @@ -1,144 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "./BaseTest.t.sol"; -import "./mock/Mocked721.sol"; -import "forge-std/Test.sol"; - -contract SignatureTest is BaseTest { - function testInvalidCounterpartySignature() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape3Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird3Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, signerPrivateKey, signerPrivateKey); - - vm.prank(account1); - vm.expectRevert(InvalidSignature.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - function testInvalidSignerSignature() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape3Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird3Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, account2PrivateKey); - - vm.prank(account1); - vm.expectRevert(InvalidSigner.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - function testTradeHashTypedData() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape3Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird3Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - bytes32 structHash = keccak256( - abi.encode( - TRADE_TYPEHASH, - keccak256(bytes(trade.id)), - trade.creator, - trade.counterparty, - trade.expiresAt, - keccak256(abi.encodePacked(trade.creatorCollections)), // address[] - keccak256(abi.encodePacked(trade.creatorIds)), // uint256[] - keccak256(abi.encodePacked(trade.counterpartyCollections)), // address[] - keccak256(abi.encodePacked(trade.counterpartyIds)) // uint256[] - ) - ); - bytes32 expectedDigest = keccak256(abi.encodePacked("\x19\x01", echo.domainSeparator(), structHash)); - // Check hash struct - assertEq(echo.hashTypedData(structHash), expectedDigest); - - (uint8 v, bytes32 r, bytes32 s) = _signTrade(trade, account2PrivateKey); - address recoveredAddress = ecrecover(expectedDigest, v, r, s); - assertEq(recoveredAddress, trade.counterparty); - } - - function testSignatureHashTypedData() public { - bytes32 structHash = - keccak256(abi.encode(SIGNATURE_TYPEHASH, mockSignature.v, mockSignature.r, mockSignature.s)); - bytes32 expectedDigest = keccak256(abi.encodePacked("\x19\x01", echo.domainSeparator(), structHash)); - // Check hash struct - assertEq(echo.hashTypedData(structHash), expectedDigest); - - (uint8 v, bytes32 r, bytes32 s) = _signSignature(mockSignature, account2PrivateKey); - address recoveredAddress = ecrecover(expectedDigest, v, r, s); - assertEq(recoveredAddress, account2); - } - - function testDomainSeparator() public { - bytes32 expectedDomainSeparator = keccak256( - abi.encode( - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), - keccak256("Echo"), - keccak256("1"), - block.chainid, - address(echo) - ) - ); - - assertEq(echo.domainSeparator(), expectedDomainSeparator); - } - - struct _testEIP5267Variables { - bytes1 fields; - string name; - string version; - uint256 chainId; - address verifyingContract; - bytes32 salt; - uint256[] extensions; - } - - function testEIP5267() public { - _testEIP5267Variables memory t; - (t.fields, t.name, t.version, t.chainId, t.verifyingContract, t.salt, t.extensions) = echo.eip712Domain(); - - assertEq(t.fields, hex"0f"); - assertEq(t.name, "Echo"); - assertEq(t.version, "1"); - assertEq(t.chainId, block.chainid); - assertEq(t.verifyingContract, address(echo)); - assertEq(t.salt, bytes32(0)); - assertEq(t.extensions, new uint256[](0)); - } -} diff --git a/test/Trade721.t.sol b/test/Trade721.t.sol index 87298b7..ff231ea 100644 --- a/test/Trade721.t.sol +++ b/test/Trade721.t.sol @@ -6,137 +6,137 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract Trade721Test is BaseTest { - // @dev Swap: 1 ape for 2 birds - function testSwapOneForTwo() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird2Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - - vm.prank(account1); - vm.expectEmit(true, true, true, true); - emit TradeExecuted("test"); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are now swapped - assertEq(apes.ownerOf(1), account2); - assertEq(birds.ownerOf(1), account1); - assertEq(birds.ownerOf(2), account1); - } - - // @dev Swap: 2 apes for 1 bird - function testSwapTwoForOne() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - creator721Collections.push(apeAddress); - creator721Ids.push(ape2Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectEmit(true, true, true, true); - emit TradeExecuted("test"); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are now swapped - assertEq(apes.ownerOf(1), account2); - assertEq(apes.ownerOf(2), account2); - assertEq(birds.ownerOf(1), account1); - } - - // @dev Swap: 2 apes for 2 birds - function testSwapTwoForTwo() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - creator721Collections.push(apeAddress); - creator721Ids.push(ape2Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird2Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectEmit(true, true, true, true); - emit TradeExecuted("test"); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are now swapped - assertEq(apes.ownerOf(1), account2); - assertEq(apes.ownerOf(2), account2); - assertEq(birds.ownerOf(1), account1); - assertEq(birds.ownerOf(2), account1); - } - - function testCannotReuseTradeId() public { - // Execute initial swap - testSwapTwoForTwo(); - - // Second swap with same Id - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - creator721Collections.push(apeAddress); - creator721Ids.push(ape2Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird2Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(TradeAlreadyExist.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } +// @dev Swap: 1 ape for 2 birds +// function testSwapOneForTwo() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird2Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// +// vm.prank(account1); +// vm.expectEmit(true, true, true, true); +// emit TradeExecuted("test"); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are now swapped +// assertEq(apes.ownerOf(1), account2); +// assertEq(birds.ownerOf(1), account1); +// assertEq(birds.ownerOf(2), account1); +// } +// +// // @dev Swap: 2 apes for 1 bird +// function testSwapTwoForOne() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape2Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectEmit(true, true, true, true); +// emit TradeExecuted("test"); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are now swapped +// assertEq(apes.ownerOf(1), account2); +// assertEq(apes.ownerOf(2), account2); +// assertEq(birds.ownerOf(1), account1); +// } +// +// // @dev Swap: 2 apes for 2 birds +// function testSwapTwoForTwo() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape2Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird2Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectEmit(true, true, true, true); +// emit TradeExecuted("test"); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are now swapped +// assertEq(apes.ownerOf(1), account2); +// assertEq(apes.ownerOf(2), account2); +// assertEq(birds.ownerOf(1), account1); +// assertEq(birds.ownerOf(2), account1); +// } +// +// function testCannotReuseTradeId() public { +// // Execute initial swap +// testSwapTwoForTwo(); +// +// // Second swap with same Id +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape2Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird2Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(TradeAlreadyExist.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } } diff --git a/test/WrongAssets.t.sol b/test/WrongAssets.t.sol index 70bf00b..61b56bd 100644 --- a/test/WrongAssets.t.sol +++ b/test/WrongAssets.t.sol @@ -5,246 +5,246 @@ import "./BaseTest.t.sol"; import "forge-std/Test.sol"; contract WrongAssetsTest is BaseTest { - function testCannotSwapEmptyCreatorAssets() public { - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird2Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(InvalidAssets.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - function testCannotSwapEmptyCounterpartyAssets() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(InvalidAssets.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - function testCannotSwapEmptyAssets() public { - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(InvalidAssets.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - } - - function testCannotTradeLongerCreatorIds() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - creator721Ids.push(ape2Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(LengthMismatch.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are not swapped - assertEq(apes.ownerOf(1), account1); - assertEq(apes.ownerOf(2), account1); - assertEq(birds.ownerOf(1), account2); - } - - function testCannotTradeLongerCreatorCollections() public { - creator721Collections.push(apeAddress); - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(LengthMismatch.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are not swapped - assertEq(apes.ownerOf(1), account1); - assertEq(birds.ownerOf(1), account2); - } - - function testCannotTradeLongerCounterpartyIds() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - counterparty721Ids.push(bird2Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(LengthMismatch.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are not swapped - assertEq(apes.ownerOf(1), account1); - assertEq(birds.ownerOf(1), account2); - assertEq(birds.ownerOf(2), account2); - } - - function testCannotTradeLongerCounterpartyCollections() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert(LengthMismatch.selector); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are not swapped - assertEq(apes.ownerOf(1), account1); - assertEq(birds.ownerOf(1), account2); - } - - function testCannotTradeSameCreatorAssets() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert("WRONG_FROM"); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are not swapped - assertEq(apes.ownerOf(1), account1); - assertEq(birds.ownerOf(1), account2); - } - - function testCannotTradeSameCounterpartyAssets() public { - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - - Trade memory trade = Trade({ - id: "test", - creator: account1, - counterparty: account2, - expiresAt: in6hours, - creatorCollections: creator721Collections, - creatorIds: creator721Ids, - counterpartyCollections: counterparty721Collections, - counterpartyIds: counterparty721Ids - }); - - (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - vm.prank(account1); - vm.expectRevert("WRONG_FROM"); - echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - - // Assets are not swapped - assertEq(apes.ownerOf(1), account1); - assertEq(birds.ownerOf(1), account2); - } +// function testCannotSwapEmptyCreatorAssets() public { +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird2Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(InvalidAssets.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } +// +// function testCannotSwapEmptyCounterpartyAssets() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(InvalidAssets.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } +// +// function testCannotSwapEmptyAssets() public { +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(InvalidAssets.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// } +// +// function testCannotTradeLongerCreatorIds() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// creator721Ids.push(ape2Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(LengthMismatch.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are not swapped +// assertEq(apes.ownerOf(1), account1); +// assertEq(apes.ownerOf(2), account1); +// assertEq(birds.ownerOf(1), account2); +// } +// +// function testCannotTradeLongerCreatorCollections() public { +// creator721Collections.push(apeAddress); +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(LengthMismatch.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are not swapped +// assertEq(apes.ownerOf(1), account1); +// assertEq(birds.ownerOf(1), account2); +// } +// +// function testCannotTradeLongerCounterpartyIds() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// counterparty721Ids.push(bird2Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(LengthMismatch.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are not swapped +// assertEq(apes.ownerOf(1), account1); +// assertEq(birds.ownerOf(1), account2); +// assertEq(birds.ownerOf(2), account2); +// } +// +// function testCannotTradeLongerCounterpartyCollections() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert(LengthMismatch.selector); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are not swapped +// assertEq(apes.ownerOf(1), account1); +// assertEq(birds.ownerOf(1), account2); +// } +// +// function testCannotTradeSameCreatorAssets() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert("WRONG_FROM"); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are not swapped +// assertEq(apes.ownerOf(1), account1); +// assertEq(birds.ownerOf(1), account2); +// } +// +// function testCannotTradeSameCounterpartyAssets() public { +// creator721Collections.push(apeAddress); +// creator721Ids.push(ape1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// counterparty721Collections.push(birdAddress); +// counterparty721Ids.push(bird1Id); +// +// Trade memory trade = Trade({ +// id: "test", +// creator: account1, +// counterparty: account2, +// expiresAt: in6hours, +// creatorCollections: creator721Collections, +// creatorIds: creator721Ids, +// counterpartyCollections: counterparty721Collections, +// counterpartyIds: counterparty721Ids +// }); +// +// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = +// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); +// vm.prank(account1); +// vm.expectRevert("WRONG_FROM"); +// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); +// +// // Assets are not swapped +// assertEq(apes.ownerOf(1), account1); +// assertEq(birds.ownerOf(1), account2); +// } } From 233e1c1ca5961209a5a5f2c2ea6579dcafb1b24e Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Tue, 7 May 2024 16:39:49 -0400 Subject: [PATCH 09/28] added accept and execute same chain --- src/EchoCrossChain.sol | 45 ++++++++++++++++++++++++++++++++---- src/EchoError.sol | 11 +++++++++ src/EchoState.sol | 25 ++++++++++++++------ src/escrow/Escrow.sol | 4 ++-- src/escrow/EscrowHandler.sol | 3 +-- 5 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 src/EchoError.sol diff --git a/src/EchoCrossChain.sol b/src/EchoCrossChain.sol index bd87e71..070fa10 100644 --- a/src/EchoCrossChain.sol +++ b/src/EchoCrossChain.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.18; import "contracts/Admin.sol"; import "contracts/Banker.sol"; +import "contracts/EchoError.sol"; import "contracts/EchoState.sol"; import "contracts/MessageValidator.sol"; import "contracts/escrow/Escrow.sol"; @@ -10,10 +11,6 @@ import "contracts/types/Offer.sol"; import "contracts/wormhole/WormholeGovernance.sol"; import "solmate/utils/ReentrancyGuard.sol"; -error InvalidSender(); -error InvalidReceiver(); -error InvalidPayment(); - contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGovernance, EchoState, MessageValidator { constructor(address owner, address wormhole, uint16 chainId, uint8 wormholeFinality) Admin(owner) @@ -23,7 +20,7 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover /** * Same chain offers */ - function createOffer(Offer calldata offer) external payable nonReentrant notPaused { + function createOffer(Offer calldata offer) external nonReentrant notPaused { // @dev Cannot accept an offer if not the receiver if (offer.sender != msg.sender) { revert InvalidSender(); @@ -32,6 +29,44 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover _createOffer(offer, _state.chainId); } + function acceptOffer(bytes32 offerId) external payable nonReentrant notPaused { + if (msg.value != tradingFee) { + revert InvalidPayment(); + } + Offer memory offer = offers[offerId]; + + if (offer.sender == address(0)) { + revert OfferDoesNotExist(); + } + if (offer.receiver != msg.sender) { + revert InvalidReceiver(); + } + + _deposit(offer.receiverItems, offer.receiver); + _acceptOffer(offerId, offer); + } + + function executeSwap(bytes32 offerId) external payable nonReentrant notPaused { + if (msg.value != tradingFee) { + revert InvalidPayment(); + } + Offer memory offer = offers[offerId]; + + if (offer.sender == address(0)) { + revert OfferDoesNotExist(); + } + + if (offer.sender != msg.sender) { + revert InvalidSender(); + } + _withdraw(offer.senderItems, offer.receiver); + _withdraw(offer.receiverItems, offer.sender); + _executeOffer(offerId, offer); + } + + /** + * Cross chain offers + */ function createCrossChainOffer(Offer calldata offer) external payable nonReentrant notPaused { // @dev Cannot accept an offer if not the receiver if (offer.sender != msg.sender) { diff --git a/src/EchoError.sol b/src/EchoError.sol new file mode 100644 index 0000000..92332c7 --- /dev/null +++ b/src/EchoError.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +error InvalidAssets(); +error InvalidOfferState(); +error InvalidPayment(); +error InvalidReceiver(); +error InvalidSender(); +error OfferAlreadyExist(); +error OfferDoesNotExist(); +error OfferHasExpired(); diff --git a/src/EchoState.sol b/src/EchoState.sol index c92ff88..98695e6 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -1,15 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; +import "contracts/EchoError.sol"; import "contracts/types/Offer.sol"; import "contracts/types/OfferItem.sol"; -error OfferAlreadyExist(); -error OfferDoesNotExist(); -error OfferHasExpired(); -error InvalidAssets(); -error InvalidOfferState(); - abstract contract EchoState { mapping(bytes32 => Offer) public offers; @@ -72,7 +67,23 @@ abstract contract EchoState { offers[offerId] = offer; } - function _acceptOffer(Offer calldata offer, uint16 chainId) internal {} + function _acceptOffer(bytes32 offerId, Offer memory offer) internal offerNotExpired(offer.expiration) { + // @dev Cannot accept an offer if it's not OPEN + if (offer.state != OfferState.OPEN) { + revert InvalidOfferState(); + } + // TODO Try if we can just change the variable + offers[offerId].state = OfferState.ACCEPTED; + } + + function _executeOffer(bytes32 offerId, Offer memory offer) internal offerNotExpired(offer.expiration) { + // @dev Cannot execute an offer if it's not ACCEPTED + if (offer.state != OfferState.ACCEPTED) { + revert InvalidOfferState(); + } + + delete offers[offerId]; + } // @dev Internal function to create a cross chain offer. We don't do a check on the addresses here // because it might be triggered from a cross chain call. The check is done in the main Echo contract diff --git a/src/escrow/Escrow.sol b/src/escrow/Escrow.sol index fa4e158..e20f61b 100644 --- a/src/escrow/Escrow.sol +++ b/src/escrow/Escrow.sol @@ -5,11 +5,11 @@ import "contracts/escrow/EscrowHandler.sol"; import "contracts/types/OfferItems.sol"; abstract contract Escrow is EscrowHandler { - function _deposit(OfferItems calldata offerItems, address from) internal { + function _deposit(OfferItems memory offerItems, address from) internal { _transferOfferItems(offerItems, from, address(this)); } - function _withdraw(OfferItems calldata offerItems, address to) internal { + function _withdraw(OfferItems memory offerItems, address to) internal { _transferOfferItems(offerItems, address(this), to); } } diff --git a/src/escrow/EscrowHandler.sol b/src/escrow/EscrowHandler.sol index 8c33799..19a54c8 100644 --- a/src/escrow/EscrowHandler.sol +++ b/src/escrow/EscrowHandler.sol @@ -10,9 +10,8 @@ abstract contract EscrowHandler is ERC721TokenReceiver { collection.safeTransferFrom(from, to, id); } - // TODO add check for chain or size 0? // @dev function to transfer items from an offer type - function _transferOfferItems(OfferItems calldata offerItems, address from, address to) internal { + function _transferOfferItems(OfferItems memory offerItems, address from, address to) internal { uint256 length = offerItems.items.length; for (uint256 i = 0; i < length;) { _transferERC721(offerItems.items[i].tokenAddress, offerItems.items[i].tokenId, from, to); From d5a12303020a81da090ddf11872b6f1c6a53390b Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Tue, 7 May 2024 18:33:11 -0400 Subject: [PATCH 10/28] pretteir --- prettier.config.js | 2 +- test/mock/MockWormhole.sol | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/prettier.config.js b/prettier.config.js index 8855a4e..ab5ce1d 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -7,7 +7,7 @@ module.exports = { plugins: ['prettier-plugin-solidity'], overrides: [ { - files: ['src/**/*.sol', 'test/**/*.sol'], + files: ['src/**/*.sol', 'test/**/*.sol', 'script/**/*.sol'], options: { parser: 'solidity-parse', printWidth: 100, diff --git a/test/mock/MockWormhole.sol b/test/mock/MockWormhole.sol index 74a90eb..a160349 100644 --- a/test/mock/MockWormhole.sol +++ b/test/mock/MockWormhole.sol @@ -1,5 +1,4 @@ // SPDX-License-Identifier: Apache 2 - pragma solidity ^0.8.18; import "contracts/wormhole/IWormhole.sol"; From d037ea73c6f084edc4b5da4c9d9d3bbf08c0fff5 Mon Sep 17 00:00:00 2001 From: Johnny Cage Wins <2409861+0xjohnnycagewins@users.noreply.github.com> Date: Fri, 10 May 2024 17:01:28 -0400 Subject: [PATCH 11/28] added create offer tests # Conflicts: # src/EchoCrossChain.sol # src/EchoState.sol --- .idea/echo-contracts.iml | 1 + .idea/inspectionProfiles/Project_Default.xml | 13 + .idea/watcherTasks.xml | 25 + package.json | 28 +- pnpm-lock.yaml | 3298 ++++++++++++++---- script/DeployEchoCrossChain.s.sol | 9 +- script/TestEchoCrossChain.s.sol | 22 - src/EchoCrossChain.sol | 38 +- src/EchoState.sol | 2 +- src/escrow/Escrow.sol | 4 +- src/escrow/EscrowHandler.sol | 2 +- src/types/Offer.sol | 4 +- src/types/OfferItems.sol | 4 +- test/BaseTest.t.sol | 68 +- test/CreateOffer.t.sol | 184 + test/Ownership.t.sol | 173 +- test/utils/OfferUtils.sol | 89 + 17 files changed, 3129 insertions(+), 835 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/watcherTasks.xml delete mode 100644 script/TestEchoCrossChain.s.sol create mode 100644 test/CreateOffer.t.sol create mode 100644 test/utils/OfferUtils.sol diff --git a/.idea/echo-contracts.iml b/.idea/echo-contracts.iml index 24643cc..c063e28 100644 --- a/.idea/echo-contracts.iml +++ b/.idea/echo-contracts.iml @@ -2,6 +2,7 @@ + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..145bfd7 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml new file mode 100644 index 0000000..ca44615 --- /dev/null +++ b/.idea/watcherTasks.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json index ff4a33e..a2cfaf9 100644 --- a/package.json +++ b/package.json @@ -9,22 +9,26 @@ ] }, "scripts": { - "pretty": "forge fmt", "build": "forge build", - "test": "forge test -vvv", - "test:bridge": "forge test --fork-url https://api.avax.network/ext/bc/C/rpc -vvv", - "test:gas-report": "forge test --gas-report", - "snapshot": "forge snapshot; cat .gas-snapshot", "coverage": "forge coverage --report lcov", "coverage:summary": "forge coverage --report summary", - "prepare": "husky install" + "prepare": "husky install", + "pretty": "forge fmt", + "modules:remove": "rm -rf node_modules; rm -rf pnpm-lock.yaml", + "modules:update": "ncu -u --deep", + "modules:update-minor": "ncu -u --deep --target=minor", + "snapshot": "forge snapshot; cat .gas-snapshot", + "test": "forge test -vvv", + "test:bridge": "forge test --fork-url https://api.avax.network/ext/bc/C/rpc -vvv", + "test:gas-report": "forge test --gas-report" }, "devDependencies": { - "husky": "^9.0.11", - "lint-staged": "^15.2.2", - "prettier": "^3.2.5", - "prettier-plugin-solidity": "^1.3.1", - "solhint": "^4.1.1", - "solhint-plugin-prettier": "^0.1.0" + "husky": "9.0.11", + "lint-staged": "15.2.2", + "npm-check-updates": "16.14.20", + "prettier": "3.2.5", + "prettier-plugin-solidity": "1.3.1", + "solhint": "4.5.4", + "solhint-plugin-prettier": "0.1.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c63c55..c1f6d10 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,304 +1,374 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -devDependencies: - husky: - specifier: ^9.0.11 - version: 9.0.11 - lint-staged: - specifier: ^15.2.2 - version: 15.2.2 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - prettier-plugin-solidity: - specifier: ^1.3.1 - version: 1.3.1(prettier@3.2.5) - solhint: - specifier: ^4.1.1 - version: 4.1.1 - solhint-plugin-prettier: - specifier: ^0.1.0 - version: 0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5) +importers: + + .: + devDependencies: + husky: + specifier: 9.0.11 + version: 9.0.11 + lint-staged: + specifier: 15.2.2 + version: 15.2.2 + npm-check-updates: + specifier: 16.14.20 + version: 16.14.20 + prettier: + specifier: 3.2.5 + version: 3.2.5 + prettier-plugin-solidity: + specifier: 1.3.1 + version: 1.3.1(prettier@3.2.5) + solhint: + specifier: 4.5.4 + version: 4.5.4 + solhint-plugin-prettier: + specifier: 0.1.0 + version: 0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5) packages: - /@babel/code-frame@7.23.5: + '@babel/code-frame@7.23.5': resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.23.4 - chalk: 2.4.2 - dev: true - /@babel/helper-validator-identifier@7.22.20: + '@babel/helper-validator-identifier@7.22.20': resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} - dev: true - /@babel/highlight@7.23.4: + '@babel/highlight@7.23.4': resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - /@pnpm/config.env-replace@1.1.0: + '@colors/colors@1.5.0': + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + + '@gar/promisify@1.1.3': + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@npmcli/fs@2.1.2': + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + '@npmcli/fs@3.1.1': + resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/git@4.1.0': + resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/installed-package-contents@2.1.0': + resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + '@npmcli/move-file@2.0.1': + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + + '@npmcli/node-gyp@3.0.0': + resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/promise-spawn@6.0.2': + resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/run-script@6.0.2': + resolution: {integrity: sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pnpm/config.env-replace@1.1.0': resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} engines: {node: '>=12.22.0'} - dev: true - /@pnpm/network.ca-file@1.0.2: + '@pnpm/network.ca-file@1.0.2': resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} engines: {node: '>=12.22.0'} - dependencies: - graceful-fs: 4.2.10 - dev: true - /@pnpm/npm-conf@2.2.2: + '@pnpm/npm-conf@2.2.2': resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} engines: {node: '>=12'} - dependencies: - '@pnpm/config.env-replace': 1.1.0 - '@pnpm/network.ca-file': 1.0.2 - config-chain: 1.1.13 - dev: true - /@prettier/sync@0.3.0(prettier@3.2.5): + '@prettier/sync@0.3.0': resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} peerDependencies: prettier: ^3.0.0 - dependencies: - prettier: 3.2.5 - dev: true - /@sindresorhus/is@5.6.0: + '@sigstore/bundle@1.1.0': + resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@sigstore/protobuf-specs@0.2.1': + resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@sigstore/sign@1.0.0': + resolution: {integrity: sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@sigstore/tuf@1.0.3': + resolution: {integrity: sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@sindresorhus/is@5.6.0': resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} engines: {node: '>=14.16'} - dev: true - /@solidity-parser/parser@0.16.2: - resolution: {integrity: sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==} - dependencies: - antlr4ts: 0.5.0-alpha.4 - dev: true - - /@solidity-parser/parser@0.17.0: + '@solidity-parser/parser@0.17.0': resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} - dev: true - /@szmarczak/http-timer@5.0.1: + '@solidity-parser/parser@0.18.0': + resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} + + '@szmarczak/http-timer@5.0.1': resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} - dependencies: - defer-to-connect: 2.0.1 - dev: true - /@types/http-cache-semantics@4.0.4: + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + + '@tufjs/canonical-json@1.0.0': + resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@tufjs/models@1.0.4': + resolution: {integrity: sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@types/http-cache-semantics@4.0.4': resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} - dev: true - /ajv@6.12.6: + '@types/semver-utils@1.1.3': + resolution: {integrity: sha512-T+YwkslhsM+CeuhYUxyAjWm7mJ5am/K10UX40RuA6k6Lc7eGtq8iY2xOzy7Vq0GOqhl/xZl5l2FwURZMTPTUww==} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - /ajv@8.12.0: + ajv@8.12.0: resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - /ansi-escapes@6.2.0: + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-escapes@6.2.0: resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} engines: {node: '>=14.16'} - dependencies: - type-fest: 3.13.1 - dev: true - /ansi-regex@5.0.1: + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - dev: true - /ansi-regex@6.0.1: + ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} - dev: true - /ansi-styles@3.2.1: + ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - /ansi-styles@4.3.0: + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - /ansi-styles@6.2.1: + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - dev: true - /antlr4@4.13.1: + antlr4@4.13.1: resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} engines: {node: '>=16'} - dev: true - /antlr4ts@0.5.0-alpha.4: - resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} - dev: true + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + + are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - /argparse@2.0.1: + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - /ast-parents@0.0.1: + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + ast-parents@0.0.1: resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} - dev: true - /astral-regex@2.0.0: + astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} - dev: true - /balanced-match@1.0.2: + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - /brace-expansion@2.0.1: + boxen@7.1.1: + resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} + engines: {node: '>=14.16'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - /braces@3.0.2: + braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - dev: true - /cacheable-lookup@7.0.0: + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + cacache@17.1.4: + resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + cacheable-lookup@7.0.0: resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} engines: {node: '>=14.16'} - dev: true - /cacheable-request@10.2.14: + cacheable-request@10.2.14: resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} engines: {node: '>=14.16'} - dependencies: - '@types/http-cache-semantics': 4.0.4 - get-stream: 6.0.1 - http-cache-semantics: 4.1.1 - keyv: 4.5.4 - mimic-response: 4.0.0 - normalize-url: 8.0.0 - responselike: 3.0.0 - dev: true - /callsites@3.1.0: + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true - /chalk@2.4.2: + camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - /chalk@4.1.2: + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - /chalk@5.3.0: + chalk@5.3.0: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true - /cli-cursor@4.0.0: + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cli-cursor@4.0.0: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - restore-cursor: 4.0.0 - dev: true - /cli-truncate@4.0.0: + cli-table3@0.6.4: + resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + engines: {node: 10.* || >= 12.*} + + cli-truncate@4.0.0: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} - dependencies: - slice-ansi: 5.0.0 - string-width: 7.1.0 - dev: true - /color-convert@1.9.3: + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - /color-convert@2.0.1: + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - /color-name@1.1.3: + color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - /color-name@1.1.4: + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - /colorette@2.0.20: + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + + colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true - /commander@10.0.1: + commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} - dev: true - /commander@11.1.0: + commander@11.1.0: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} - dev: true - /config-chain@1.1.13: + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - dependencies: - ini: 1.3.8 - proto-list: 1.2.4 - dev: true - /cosmiconfig@8.3.6: + configstore@6.0.0: + resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} + engines: {node: '>=12'} + + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + + cosmiconfig@8.3.6: resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} engines: {node: '>=14'} peerDependencies: @@ -306,23 +376,16 @@ packages: peerDependenciesMeta: typescript: optional: true - dependencies: - import-fresh: 3.3.0 - js-yaml: 4.1.0 - parse-json: 5.2.0 - path-type: 4.0.0 - dev: true - /cross-spawn@7.0.3: + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - /debug@4.3.4: + crypto-random-string@4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} + + debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -330,811 +393,2742 @@ packages: peerDependenciesMeta: supports-color: optional: true - dependencies: - ms: 2.1.2 - dev: true - /decompress-response@6.0.0: + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - dependencies: - mimic-response: 3.1.0 - dev: true - /deep-extend@0.6.0: + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} - dev: true - /defer-to-connect@2.0.1: + defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} - dev: true - /emoji-regex@10.3.0: + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dot-prop@6.0.1: + resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} + engines: {node: '>=10'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + emoji-regex@10.3.0: resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} - dev: true - /emoji-regex@8.0.0: + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true - /error-ex@1.3.2: + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - /escape-string-regexp@1.0.5: + escape-goat@4.0.0: + resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} + engines: {node: '>=12'} + + escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} - dev: true - /eventemitter3@5.0.1: + eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - dev: true - /execa@8.0.1: + execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - dev: true - /fast-deep-equal@3.1.3: + exponential-backoff@3.1.1: + resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - /fast-diff@1.3.0: + fast-diff@1.3.0: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - dev: true - /fast-json-stable-stringify@2.1.0: + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - /fill-range@7.0.1: + fast-memoize@2.5.2: + resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - /form-data-encoder@2.1.4: + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + + form-data-encoder@2.1.4: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} - dev: true - /fs.realpath@1.0.0: + fp-and-or@0.1.4: + resolution: {integrity: sha512-+yRYRhpnFPWXSly/6V4Lw9IfOV26uu30kynGJ03PW+MnjOEQe45RZ141QcS0aJehYBYA50GfCDnsRbFJdhssRw==} + engines: {node: '>=10'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs-minipass@3.0.3: + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - /get-east-asian-width@1.2.0: + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + get-east-asian-width@1.2.0: resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} engines: {node: '>=18'} - dev: true - /get-stream@6.0.1: + get-stdin@8.0.0: + resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} + engines: {node: '>=10'} + + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - dev: true - /get-stream@8.0.1: + get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} - dev: true - /glob@8.1.0: + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@10.3.12: + resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + + glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - dev: true - /got@12.6.1: + global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + got@12.6.1: resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} engines: {node: '>=14.16'} - dependencies: - '@sindresorhus/is': 5.6.0 - '@szmarczak/http-timer': 5.0.1 - cacheable-lookup: 7.0.0 - cacheable-request: 10.2.14 - decompress-response: 6.0.0 - form-data-encoder: 2.1.4 - get-stream: 6.0.1 - http2-wrapper: 2.2.1 - lowercase-keys: 3.0.0 - p-cancelable: 3.0.0 - responselike: 3.0.0 - dev: true - /graceful-fs@4.2.10: + graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - dev: true - /has-flag@3.0.0: + has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} - dev: true - /has-flag@4.0.0: + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: true - /http-cache-semantics@4.1.1: + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + has-yarn@3.0.0: + resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hosted-git-info@5.2.1: + resolution: {integrity: sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + hosted-git-info@6.1.1: + resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: true - /http2-wrapper@2.2.1: + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + http2-wrapper@2.2.1: resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} engines: {node: '>=10.19.0'} - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - dev: true - /human-signals@5.0.0: + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - dev: true - /husky@9.0.11: + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + husky@9.0.11: resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} engines: {node: '>=18'} hasBin: true - dev: true - /ignore@5.3.1: + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore-walk@6.0.5: + resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} - dev: true - /import-fresh@3.3.0: + import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - /inflight@1.0.6: + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - /inherits@2.0.4: + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - /ini@1.3.8: + ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - /is-arrayish@0.2.1: + ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + + ini@4.1.2: + resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - /is-fullwidth-code-point@3.0.0: + is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true + + is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - dev: true - /is-fullwidth-code-point@4.0.0: + is-fullwidth-code-point@4.0.0: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} - dev: true - /is-fullwidth-code-point@5.0.0: + is-fullwidth-code-point@5.0.0: resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} engines: {node: '>=18'} - dependencies: - get-east-asian-width: 1.2.0 - dev: true - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + is-installed-globally@0.4.0: + resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} + engines: {node: '>=10'} + + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + + is-npm@6.0.0: + resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + is-yarn-global@0.4.1: + resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} + engines: {node: '>=12'} - /isexe@2.0.0: + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - /js-tokens@4.0.0: + jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - /js-yaml@4.1.0: + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - /json-buffer@3.0.1: + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - /json-parse-even-better-errors@2.3.1: + json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - /json-schema-traverse@0.4.1: + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + json-parse-helpfulerror@1.0.3: + resolution: {integrity: sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==} + + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - /json-schema-traverse@1.0.0: + json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - /keyv@4.5.4: + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonlines@0.1.1: + resolution: {integrity: sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - /latest-version@7.0.0: + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + latest-version@7.0.0: resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} engines: {node: '>=14.16'} - dependencies: - package-json: 8.1.1 - dev: true - /lilconfig@3.0.0: + lilconfig@3.0.0: resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} engines: {node: '>=14'} - dev: true - /lines-and-columns@1.2.4: + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - /lint-staged@15.2.2: + lint-staged@15.2.2: resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} engines: {node: '>=18.12.0'} hasBin: true - dependencies: - chalk: 5.3.0 - commander: 11.1.0 - debug: 4.3.4 - execa: 8.0.1 - lilconfig: 3.0.0 - listr2: 8.0.1 - micromatch: 4.0.5 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.3.4 - transitivePeerDependencies: - - supports-color - dev: true - /listr2@8.0.1: + listr2@8.0.1: resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} engines: {node: '>=18.0.0'} - dependencies: - cli-truncate: 4.0.0 - colorette: 2.0.20 - eventemitter3: 5.0.1 - log-update: 6.0.0 - rfdc: 1.3.1 - wrap-ansi: 9.0.0 - dev: true - /lodash.truncate@4.4.2: + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true - /lodash@4.17.21: + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - /log-update@6.0.0: + log-update@6.0.0: resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} engines: {node: '>=18'} - dependencies: - ansi-escapes: 6.2.0 - cli-cursor: 4.0.0 - slice-ansi: 7.1.0 - strip-ansi: 7.1.0 - wrap-ansi: 9.0.0 - dev: true - /lowercase-keys@3.0.0: + lowercase-keys@3.0.0: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - /lru-cache@6.0.0: + lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + + lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - /merge-stream@2.0.0: + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + make-fetch-happen@11.1.1: + resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - /micromatch@4.0.5: + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - /mimic-fn@2.1.0: + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - dev: true - /mimic-fn@4.0.0: + mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - dev: true - /mimic-response@3.1.0: + mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - dev: true - /mimic-response@4.0.0: + mimic-response@4.0.0: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - /minimatch@5.1.6: + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - /minimist@1.2.8: + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true - /ms@2.1.2: + minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + + minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + minipass-fetch@3.0.5: + resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + + minipass-json-stream@1.0.1: + resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.1.0: + resolution: {integrity: sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - /normalize-url@8.0.0: + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + node-gyp@9.4.1: + resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} + engines: {node: ^12.13 || ^14.13 || >=16} + hasBin: true + + nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + + normalize-package-data@5.0.0: + resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + normalize-url@8.0.0: resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} engines: {node: '>=14.16'} - dev: true - /npm-run-path@5.3.0: + npm-bundled@3.0.1: + resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-check-updates@16.14.20: + resolution: {integrity: sha512-sYbIhun4DrjO7NFOTdvs11nCar0etEhZTsEjL47eM0TuiGMhmYughRCxG2SpGRmGAQ7AkwN7bw2lWzoE7q6yOQ==} + engines: {node: '>=14.14'} + hasBin: true + + npm-install-checks@6.3.0: + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-normalize-package-bin@3.0.1: + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-package-arg@10.1.0: + resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-packlist@7.0.4: + resolution: {integrity: sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-pick-manifest@8.0.2: + resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-registry-fetch@14.0.5: + resolution: {integrity: sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: true - /once@1.4.0: + npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - /onetime@5.1.2: + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - /onetime@6.0.0: + onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: true - /p-cancelable@3.0.0: + p-cancelable@3.0.0: resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} engines: {node: '>=12.20'} - dev: true - /package-json@8.1.1: + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + package-json@8.1.1: resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} engines: {node: '>=14.16'} - dependencies: - got: 12.6.1 - registry-auth-token: 5.0.2 - registry-url: 6.0.1 - semver: 7.6.0 - dev: true - /parent-module@1.0.1: + pacote@15.2.0: + resolution: {integrity: sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - /parse-json@5.2.0: + parse-github-url@1.0.2: + resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==} + engines: {node: '>=0.10.0'} + hasBin: true + + parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.23.5 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - /path-key@3.1.1: + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - dev: true - /path-key@4.0.0: + path-key@4.0.0: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - dev: true - /path-type@4.0.0: + path-scurry@1.10.2: + resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} + engines: {node: '>=16 || 14 >=14.17'} + + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true - /picomatch@2.3.1: + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - dev: true - /pidtree@0.6.0: + pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'} hasBin: true - dev: true - /pluralize@8.0.0: + pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - dev: true - /prettier-linter-helpers@1.0.0: + prettier-linter-helpers@1.0.0: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - dependencies: - fast-diff: 1.3.0 - dev: true - /prettier-plugin-solidity@1.3.1(prettier@3.2.5): + prettier-plugin-solidity@1.3.1: resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} engines: {node: '>=16'} peerDependencies: prettier: '>=2.3.0' - dependencies: - '@solidity-parser/parser': 0.17.0 - prettier: 3.2.5 - semver: 7.6.0 - solidity-comments-extractor: 0.0.8 - dev: true - /prettier@2.8.8: + prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} hasBin: true - requiresBuild: true - dev: true - optional: true - /prettier@3.2.5: + prettier@3.2.5: resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} engines: {node: '>=14'} hasBin: true - dev: true - /proto-list@1.2.4: + proc-log@3.0.0: + resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + prompts-ncu@3.0.0: + resolution: {integrity: sha512-qyz9UxZ5MlPKWVhWrCmSZ1ahm2GVYdjLb8og2sg0IPth1KRuhcggHGuijz0e41dkx35p1t1q3GRISGH7QGALFA==} + engines: {node: '>= 14'} + + proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - dev: true - /punycode@2.3.1: + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - dev: true - /quick-lru@5.1.1: + pupa@3.1.0: + resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} + engines: {node: '>=12.20'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} - dev: true - /rc@1.2.8: + rc-config-loader@4.1.3: + resolution: {integrity: sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==} + + rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - dev: true - /registry-auth-token@5.0.2: + read-package-json-fast@3.0.2: + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + read-package-json@6.0.4: + resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + registry-auth-token@5.0.2: resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} engines: {node: '>=14'} - dependencies: - '@pnpm/npm-conf': 2.2.2 - dev: true - /registry-url@6.0.1: + registry-url@6.0.1: resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} engines: {node: '>=12'} - dependencies: - rc: 1.2.8 - dev: true - /require-from-string@2.0.2: + remote-git-tags@3.0.0: + resolution: {integrity: sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==} + engines: {node: '>=8'} + + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - dev: true - /resolve-alpn@1.2.1: + resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - dev: true - /resolve-from@4.0.0: + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true - /responselike@3.0.0: + responselike@3.0.0: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} engines: {node: '>=14.16'} - dependencies: - lowercase-keys: 3.0.0 - dev: true - /restore-cursor@4.0.0: + restore-cursor@4.0.0: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: true - /rfdc@1.3.1: + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.3.1: resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - dev: true - /semver@7.6.0: + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + + rimraf@5.0.5: + resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} + engines: {node: '>=14'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver-diff@4.0.0: + resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} + engines: {node: '>=12'} + + semver-utils@1.1.4: + resolution: {integrity: sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==} + + semver@7.6.0: resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} engines: {node: '>=10'} hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - /shebang-command@2.0.0: + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - /shebang-regex@3.0.0: + shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - dev: true - /signal-exit@3.0.7: + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - /signal-exit@4.1.0: + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - dev: true - /slice-ansi@4.0.0: + sigstore@1.9.0: + resolution: {integrity: sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - /slice-ansi@5.0.0: + slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 4.0.0 - dev: true - /slice-ansi@7.1.0: + slice-ansi@7.1.0: resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} engines: {node: '>=18'} - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 5.0.0 - dev: true - /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5): + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + + socks@2.8.3: + resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + solhint-plugin-prettier@0.1.0: resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} peerDependencies: prettier: ^3.0.0 prettier-plugin-solidity: ^1.0.0 - dependencies: - '@prettier/sync': 0.3.0(prettier@3.2.5) - prettier: 3.2.5 - prettier-linter-helpers: 1.0.0 - prettier-plugin-solidity: 1.3.1(prettier@3.2.5) - dev: true - /solhint@4.1.1: - resolution: {integrity: sha512-7G4iF8H5hKHc0tR+/uyZesSKtfppFIMvPSW+Ku6MSL25oVRuyFeqNhOsXHfkex64wYJyXs4fe+pvhB069I19Tw==} + solhint@4.5.4: + resolution: {integrity: sha512-Cu1XiJXub2q1eCr9kkJ9VPv1sGcmj3V7Zb76B0CoezDOB9bu3DxKIFFH7ggCl9fWpEPD6xBmRLfZrYijkVmujQ==} hasBin: true - dependencies: - '@solidity-parser/parser': 0.16.2 - ajv: 6.12.6 - antlr4: 4.13.1 - ast-parents: 0.0.1 - chalk: 4.1.2 - commander: 10.0.1 - cosmiconfig: 8.3.6 - fast-diff: 1.3.0 - glob: 8.1.0 - ignore: 5.3.1 - js-yaml: 4.1.0 - latest-version: 7.0.0 - lodash: 4.17.21 - pluralize: 8.0.0 - semver: 7.6.0 - strip-ansi: 6.0.1 - table: 6.8.1 - text-table: 0.2.0 - optionalDependencies: - prettier: 2.8.8 - transitivePeerDependencies: - - typescript - dev: true - /solidity-comments-extractor@0.0.8: + solidity-comments-extractor@0.0.8: resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} - dev: true - /string-argv@0.3.2: + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spawn-please@2.0.2: + resolution: {integrity: sha512-KM8coezO6ISQ89c1BzyWNtcn2V2kAVtwIXd3cN/V5a0xPYc1F/vydrRc01wsKFEQ/p+V1a4sw4z2yMITIXrgGw==} + engines: {node: '>=14'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.17: + resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + ssri@10.0.6: + resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} - dev: true - /string-width@4.2.3: + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: true - /string-width@7.1.0: + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.1.0: resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} engines: {node: '>=18'} - dependencies: - emoji-regex: 10.3.0 - get-east-asian-width: 1.2.0 - strip-ansi: 7.1.0 - dev: true - /strip-ansi@6.0.1: + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - dev: true - /strip-ansi@7.1.0: + strip-ansi@7.1.0: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - /strip-final-newline@3.0.0: + strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} - dev: true - /strip-json-comments@2.0.1: + strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} - dev: true - /supports-color@5.5.0: + strip-json-comments@5.0.1: + resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} + engines: {node: '>=14.16'} + + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - /supports-color@7.2.0: + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - /table@6.8.1: + table@6.8.1: resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} engines: {node: '>=10.0.0'} - dependencies: - ajv: 8.12.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - /text-table@0.2.0: + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - /to-regex-range@5.0.1: + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - /type-fest@3.13.1: + tuf-js@1.1.7: + resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-fest@3.13.1: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} engines: {node: '>=14.16'} - dev: true - /uri-js@4.4.1: + typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + + unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + unique-filename@3.0.0: + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + unique-slug@4.0.0: + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + unique-string@3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} + + untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + + update-notifier@6.0.2: + resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} + engines: {node: '>=14.16'} + + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - /which@2.0.2: + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - /wrap-ansi@9.0.0: + which@3.0.1: + resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} - dependencies: - ansi-styles: 6.2.1 - string-width: 7.1.0 - strip-ansi: 7.1.0 - dev: true - /wrappy@1.0.2: + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - /yallist@4.0.0: + write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + + xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + + yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - /yaml@2.3.4: + yaml@2.3.4: resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} engines: {node: '>= 14'} - dev: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@babel/code-frame@7.23.5': + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + + '@babel/helper-validator-identifier@7.22.20': {} + + '@babel/highlight@7.23.4': + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + + '@colors/colors@1.5.0': + optional: true + + '@gar/promisify@1.1.3': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@npmcli/fs@2.1.2': + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.6.0 + + '@npmcli/fs@3.1.1': + dependencies: + semver: 7.6.0 + + '@npmcli/git@4.1.0': + dependencies: + '@npmcli/promise-spawn': 6.0.2 + lru-cache: 7.18.3 + npm-pick-manifest: 8.0.2 + proc-log: 3.0.0 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.6.0 + which: 3.0.1 + transitivePeerDependencies: + - bluebird + + '@npmcli/installed-package-contents@2.1.0': + dependencies: + npm-bundled: 3.0.1 + npm-normalize-package-bin: 3.0.1 + + '@npmcli/move-file@2.0.1': + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + + '@npmcli/node-gyp@3.0.0': {} + + '@npmcli/promise-spawn@6.0.2': + dependencies: + which: 3.0.1 + + '@npmcli/run-script@6.0.2': + dependencies: + '@npmcli/node-gyp': 3.0.0 + '@npmcli/promise-spawn': 6.0.2 + node-gyp: 9.4.1 + read-package-json-fast: 3.0.2 + which: 3.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pnpm/config.env-replace@1.1.0': {} + + '@pnpm/network.ca-file@1.0.2': + dependencies: + graceful-fs: 4.2.10 + + '@pnpm/npm-conf@2.2.2': + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + + '@prettier/sync@0.3.0(prettier@3.2.5)': + dependencies: + prettier: 3.2.5 + + '@sigstore/bundle@1.1.0': + dependencies: + '@sigstore/protobuf-specs': 0.2.1 + + '@sigstore/protobuf-specs@0.2.1': {} + + '@sigstore/sign@1.0.0': + dependencies: + '@sigstore/bundle': 1.1.0 + '@sigstore/protobuf-specs': 0.2.1 + make-fetch-happen: 11.1.1 + transitivePeerDependencies: + - supports-color + + '@sigstore/tuf@1.0.3': + dependencies: + '@sigstore/protobuf-specs': 0.2.1 + tuf-js: 1.1.7 + transitivePeerDependencies: + - supports-color + + '@sindresorhus/is@5.6.0': {} + + '@solidity-parser/parser@0.17.0': {} + + '@solidity-parser/parser@0.18.0': {} + + '@szmarczak/http-timer@5.0.1': + dependencies: + defer-to-connect: 2.0.1 + + '@tootallnate/once@2.0.0': {} + + '@tufjs/canonical-json@1.0.0': {} + + '@tufjs/models@1.0.4': + dependencies: + '@tufjs/canonical-json': 1.0.0 + minimatch: 9.0.4 + + '@types/http-cache-semantics@4.0.4': {} + + '@types/semver-utils@1.1.3': {} + + abbrev@1.1.1: {} + + agent-base@6.0.2: + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + agentkeepalive@4.5.0: + dependencies: + humanize-ms: 1.2.1 + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.12.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-escapes@6.2.0: + dependencies: + type-fest: 3.13.1 + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + antlr4@4.13.1: {} + + aproba@2.0.0: {} + + are-we-there-yet@3.0.1: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + + argparse@2.0.1: {} + + array-union@2.1.0: {} + + ast-parents@0.0.1: {} + + astral-regex@2.0.0: {} + + balanced-match@1.0.2: {} + + boxen@7.1.1: + dependencies: + ansi-align: 3.0.1 + camelcase: 7.0.1 + chalk: 5.3.0 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.1.0 + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.2: + dependencies: + fill-range: 7.0.1 + + buffer-from@1.1.2: {} + + cacache@16.1.3: + dependencies: + '@npmcli/fs': 2.1.2 + '@npmcli/move-file': 2.0.1 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 8.1.0 + infer-owner: 1.0.4 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 9.0.1 + tar: 6.2.1 + unique-filename: 2.0.1 + transitivePeerDependencies: + - bluebird + + cacache@17.1.4: + dependencies: + '@npmcli/fs': 3.1.1 + fs-minipass: 3.0.3 + glob: 10.3.12 + lru-cache: 7.18.3 + minipass: 7.1.0 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + p-map: 4.0.0 + ssri: 10.0.6 + tar: 6.2.1 + unique-filename: 3.0.0 + + cacheable-lookup@7.0.0: {} + + cacheable-request@10.2.14: + dependencies: + '@types/http-cache-semantics': 4.0.4 + get-stream: 6.0.1 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + mimic-response: 4.0.0 + normalize-url: 8.0.0 + responselike: 3.0.0 + + callsites@3.1.0: {} + + camelcase@7.0.1: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + chownr@2.0.0: {} + + ci-info@3.9.0: {} + + clean-stack@2.2.0: {} + + cli-boxes@3.0.0: {} + + cli-cursor@4.0.0: + dependencies: + restore-cursor: 4.0.0 + + cli-table3@0.6.4: + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.1.0 + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-support@1.1.3: {} + + colorette@2.0.20: {} + + commander@10.0.1: {} + + commander@11.1.0: {} + + concat-map@0.0.1: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + + configstore@6.0.0: + dependencies: + dot-prop: 6.0.1 + graceful-fs: 4.2.10 + unique-string: 3.0.0 + write-file-atomic: 3.0.3 + xdg-basedir: 5.1.0 + + console-control-strings@1.1.0: {} + + cosmiconfig@8.3.6: + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-random-string@4.0.0: + dependencies: + type-fest: 1.4.0 + + debug@4.3.4: + dependencies: + ms: 2.1.2 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + deep-extend@0.6.0: {} + + defer-to-connect@2.0.1: {} + + delegates@1.0.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dot-prop@6.0.1: + dependencies: + is-obj: 2.0.0 + + eastasianwidth@0.2.0: {} + + emoji-regex@10.3.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + optional: true + + env-paths@2.2.1: {} + + err-code@2.0.3: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + escape-goat@4.0.0: {} + + escape-string-regexp@1.0.5: {} + + eventemitter3@5.0.1: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + exponential-backoff@3.1.1: {} + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + + fast-json-stable-stringify@2.1.0: {} + + fast-memoize@2.5.2: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fill-range@7.0.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + foreground-child@3.1.1: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + form-data-encoder@2.1.4: {} + + fp-and-or@0.1.4: {} + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fs-minipass@3.0.3: + dependencies: + minipass: 7.1.0 + + fs.realpath@1.0.0: {} + + function-bind@1.1.2: {} + + gauge@4.0.4: + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + + get-east-asian-width@1.2.0: {} + + get-stdin@8.0.0: {} + + get-stream@6.0.1: {} + + get-stream@8.0.1: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob@10.3.12: + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.4 + minipass: 7.1.0 + path-scurry: 1.10.2 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + global-dirs@3.0.1: + dependencies: + ini: 2.0.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + + got@12.6.1: + dependencies: + '@sindresorhus/is': 5.6.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.14 + decompress-response: 6.0.0 + form-data-encoder: 2.1.4 + get-stream: 6.0.1 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 + + graceful-fs@4.2.10: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-unicode@2.0.1: {} + + has-yarn@3.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hosted-git-info@5.2.1: + dependencies: + lru-cache: 7.18.3 + + hosted-git-info@6.1.1: + dependencies: + lru-cache: 7.18.3 + + http-cache-semantics@4.1.1: {} + + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + http2-wrapper@2.2.1: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + human-signals@5.0.0: {} + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.2 + + husky@9.0.11: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + optional: true + + ignore-walk@6.0.5: + dependencies: + minimatch: 9.0.4 + + ignore@5.3.1: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-lazy@4.0.0: {} + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + infer-owner@1.0.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@2.0.0: {} + + ini@4.1.2: {} + + ip-address@9.0.5: + dependencies: + jsbn: 1.1.0 + sprintf-js: 1.1.3 + + is-arrayish@0.2.1: {} + + is-ci@3.0.1: + dependencies: + ci-info: 3.9.0 + + is-core-module@2.13.1: + dependencies: + hasown: 2.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.2.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-installed-globally@0.4.0: + dependencies: + global-dirs: 3.0.1 + is-path-inside: 3.0.3 + + is-lambda@1.0.1: {} + + is-npm@6.0.0: {} + + is-number@7.0.0: {} + + is-obj@2.0.0: {} + + is-path-inside@3.0.3: {} + + is-stream@3.0.0: {} + + is-typedarray@1.0.0: {} + + is-yarn-global@0.4.1: {} + + isexe@2.0.0: {} + + jackspeak@2.3.6: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jju@1.4.0: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsbn@1.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-parse-even-better-errors@3.0.2: {} + + json-parse-helpfulerror@1.0.3: + dependencies: + jju: 1.4.0 + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json5@2.2.3: {} + + jsonlines@0.1.1: {} + + jsonparse@1.3.1: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kleur@4.1.5: {} + + latest-version@7.0.0: + dependencies: + package-json: 8.1.1 + + lilconfig@3.0.0: {} + + lines-and-columns@1.2.4: {} + + lint-staged@15.2.2: + dependencies: + chalk: 5.3.0 + commander: 11.1.0 + debug: 4.3.4 + execa: 8.0.1 + lilconfig: 3.0.0 + listr2: 8.0.1 + micromatch: 4.0.5 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.3.4 + transitivePeerDependencies: + - supports-color + + listr2@8.0.1: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.0.0 + rfdc: 1.3.1 + wrap-ansi: 9.0.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.truncate@4.4.2: {} + + lodash@4.17.21: {} + + log-update@6.0.0: + dependencies: + ansi-escapes: 6.2.0 + cli-cursor: 4.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + + lowercase-keys@3.0.0: {} + + lru-cache@10.2.2: {} + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@7.18.3: {} + + make-fetch-happen@10.2.1: + dependencies: + agentkeepalive: 4.5.0 + cacache: 16.1.3 + http-cache-semantics: 4.1.1 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 2.1.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 9.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + + make-fetch-happen@11.1.1: + dependencies: + agentkeepalive: 4.5.0 + cacache: 17.1.4 + http-cache-semantics: 4.1.1 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 5.0.0 + minipass-fetch: 3.0.5 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 10.0.6 + transitivePeerDependencies: + - supports-color + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.5: + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + + mimic-fn@2.1.0: {} + + mimic-fn@4.0.0: {} + + mimic-response@3.1.0: {} + + mimic-response@4.0.0: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.4: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass-collect@1.0.2: + dependencies: + minipass: 3.3.6 + + minipass-fetch@2.1.2: + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + + minipass-fetch@3.0.5: + dependencies: + minipass: 7.1.0 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + + minipass-flush@1.0.5: + dependencies: + minipass: 3.3.6 + + minipass-json-stream@1.0.1: + dependencies: + jsonparse: 1.3.1 + minipass: 3.3.6 + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@5.0.0: {} + + minipass@7.1.0: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mkdirp@1.0.4: {} + + ms@2.1.2: {} + + negotiator@0.6.3: {} + + node-gyp@9.4.1: + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.1 + glob: 7.2.3 + graceful-fs: 4.2.10 + make-fetch-happen: 10.2.1 + nopt: 6.0.0 + npmlog: 6.0.2 + rimraf: 3.0.2 + semver: 7.6.0 + tar: 6.2.1 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + + nopt@6.0.0: + dependencies: + abbrev: 1.1.1 + + normalize-package-data@5.0.0: + dependencies: + hosted-git-info: 6.1.1 + is-core-module: 2.13.1 + semver: 7.6.0 + validate-npm-package-license: 3.0.4 + + normalize-url@8.0.0: {} + + npm-bundled@3.0.1: + dependencies: + npm-normalize-package-bin: 3.0.1 + + npm-check-updates@16.14.20: + dependencies: + '@types/semver-utils': 1.1.3 + chalk: 5.3.0 + cli-table3: 0.6.4 + commander: 10.0.1 + fast-memoize: 2.5.2 + find-up: 5.0.0 + fp-and-or: 0.1.4 + get-stdin: 8.0.0 + globby: 11.1.0 + hosted-git-info: 5.2.1 + ini: 4.1.2 + js-yaml: 4.1.0 + json-parse-helpfulerror: 1.0.3 + jsonlines: 0.1.1 + lodash: 4.17.21 + make-fetch-happen: 11.1.1 + minimatch: 9.0.4 + p-map: 4.0.0 + pacote: 15.2.0 + parse-github-url: 1.0.2 + progress: 2.0.3 + prompts-ncu: 3.0.0 + rc-config-loader: 4.1.3 + remote-git-tags: 3.0.0 + rimraf: 5.0.5 + semver: 7.6.0 + semver-utils: 1.1.4 + source-map-support: 0.5.21 + spawn-please: 2.0.2 + strip-ansi: 7.1.0 + strip-json-comments: 5.0.1 + untildify: 4.0.0 + update-notifier: 6.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + + npm-install-checks@6.3.0: + dependencies: + semver: 7.6.0 + + npm-normalize-package-bin@3.0.1: {} + + npm-package-arg@10.1.0: + dependencies: + hosted-git-info: 6.1.1 + proc-log: 3.0.0 + semver: 7.6.0 + validate-npm-package-name: 5.0.1 + + npm-packlist@7.0.4: + dependencies: + ignore-walk: 6.0.5 + + npm-pick-manifest@8.0.2: + dependencies: + npm-install-checks: 6.3.0 + npm-normalize-package-bin: 3.0.1 + npm-package-arg: 10.1.0 + semver: 7.6.0 + + npm-registry-fetch@14.0.5: + dependencies: + make-fetch-happen: 11.1.1 + minipass: 5.0.0 + minipass-fetch: 3.0.5 + minipass-json-stream: 1.0.1 + minizlib: 2.1.2 + npm-package-arg: 10.1.0 + proc-log: 3.0.0 + transitivePeerDependencies: + - supports-color + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + npmlog@6.0.2: + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + p-cancelable@3.0.0: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + package-json@8.1.1: + dependencies: + got: 12.6.1 + registry-auth-token: 5.0.2 + registry-url: 6.0.1 + semver: 7.6.0 + + pacote@15.2.0: + dependencies: + '@npmcli/git': 4.1.0 + '@npmcli/installed-package-contents': 2.1.0 + '@npmcli/promise-spawn': 6.0.2 + '@npmcli/run-script': 6.0.2 + cacache: 17.1.4 + fs-minipass: 3.0.3 + minipass: 5.0.0 + npm-package-arg: 10.1.0 + npm-packlist: 7.0.4 + npm-pick-manifest: 8.0.2 + npm-registry-fetch: 14.0.5 + proc-log: 3.0.0 + promise-retry: 2.0.1 + read-package-json: 6.0.4 + read-package-json-fast: 3.0.2 + sigstore: 1.9.0 + ssri: 10.0.6 + tar: 6.2.1 + transitivePeerDependencies: + - bluebird + - supports-color + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-github-url@1.0.2: {} + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.23.5 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-scurry@1.10.2: + dependencies: + lru-cache: 10.2.2 + minipass: 7.1.0 + + path-type@4.0.0: {} + + picomatch@2.3.1: {} + + pidtree@0.6.0: {} + + pluralize@8.0.0: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + + prettier-plugin-solidity@1.3.1(prettier@3.2.5): + dependencies: + '@solidity-parser/parser': 0.17.0 + prettier: 3.2.5 + semver: 7.6.0 + solidity-comments-extractor: 0.0.8 + + prettier@2.8.8: + optional: true + + prettier@3.2.5: {} + + proc-log@3.0.0: {} + + progress@2.0.3: {} + + promise-inflight@1.0.1: {} + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + + prompts-ncu@3.0.0: + dependencies: + kleur: 4.1.5 + sisteransi: 1.0.5 + + proto-list@1.2.4: {} + + punycode@2.3.1: {} + + pupa@3.1.0: + dependencies: + escape-goat: 4.0.0 + + queue-microtask@1.2.3: {} + + quick-lru@5.1.1: {} + + rc-config-loader@4.1.3: + dependencies: + debug: 4.3.4 + js-yaml: 4.1.0 + json5: 2.2.3 + require-from-string: 2.0.2 + transitivePeerDependencies: + - supports-color + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + + read-package-json-fast@3.0.2: + dependencies: + json-parse-even-better-errors: 3.0.2 + npm-normalize-package-bin: 3.0.1 + + read-package-json@6.0.4: + dependencies: + glob: 10.3.12 + json-parse-even-better-errors: 3.0.2 + normalize-package-data: 5.0.0 + npm-normalize-package-bin: 3.0.1 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + registry-auth-token@5.0.2: + dependencies: + '@pnpm/npm-conf': 2.2.2 + + registry-url@6.0.1: + dependencies: + rc: 1.2.8 + + remote-git-tags@3.0.0: {} + + require-from-string@2.0.2: {} + + resolve-alpn@1.2.1: {} + + resolve-from@4.0.0: {} + + responselike@3.0.0: + dependencies: + lowercase-keys: 3.0.0 + + restore-cursor@4.0.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + retry@0.12.0: {} + + reusify@1.0.4: {} + + rfdc@1.3.1: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rimraf@5.0.5: + dependencies: + glob: 10.3.12 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: + optional: true + + semver-diff@4.0.0: + dependencies: + semver: 7.6.0 + + semver-utils@1.1.4: {} + + semver@7.6.0: + dependencies: + lru-cache: 6.0.0 + + set-blocking@2.0.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sigstore@1.9.0: + dependencies: + '@sigstore/bundle': 1.1.0 + '@sigstore/protobuf-specs': 0.2.1 + '@sigstore/sign': 1.0.0 + '@sigstore/tuf': 1.0.3 + make-fetch-happen: 11.1.1 + transitivePeerDependencies: + - supports-color + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + + smart-buffer@4.2.0: {} + + socks-proxy-agent@7.0.0: + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + socks: 2.8.3 + transitivePeerDependencies: + - supports-color + + socks@2.8.3: + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + + solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5): + dependencies: + '@prettier/sync': 0.3.0(prettier@3.2.5) + prettier: 3.2.5 + prettier-linter-helpers: 1.0.0 + prettier-plugin-solidity: 1.3.1(prettier@3.2.5) + + solhint@4.5.4: + dependencies: + '@solidity-parser/parser': 0.18.0 + ajv: 6.12.6 + antlr4: 4.13.1 + ast-parents: 0.0.1 + chalk: 4.1.2 + commander: 10.0.1 + cosmiconfig: 8.3.6 + fast-diff: 1.3.0 + glob: 8.1.0 + ignore: 5.3.1 + js-yaml: 4.1.0 + latest-version: 7.0.0 + lodash: 4.17.21 + pluralize: 8.0.0 + semver: 7.6.0 + strip-ansi: 6.0.1 + table: 6.8.1 + text-table: 0.2.0 + optionalDependencies: + prettier: 2.8.8 + transitivePeerDependencies: + - typescript + + solidity-comments-extractor@0.0.8: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + spawn-please@2.0.2: + dependencies: + cross-spawn: 7.0.3 + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.17 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.17 + + spdx-license-ids@3.0.17: {} + + sprintf-js@1.1.3: {} + + ssri@10.0.6: + dependencies: + minipass: 7.1.0 + + ssri@9.0.1: + dependencies: + minipass: 3.3.6 + + string-argv@0.3.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.1.0: + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + + strip-final-newline@3.0.0: {} + + strip-json-comments@2.0.1: {} + + strip-json-comments@5.0.1: {} + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + table@6.8.1: + dependencies: + ajv: 8.12.0 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + text-table@0.2.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tuf-js@1.1.7: + dependencies: + '@tufjs/models': 1.0.4 + debug: 4.3.4 + make-fetch-happen: 11.1.1 + transitivePeerDependencies: + - supports-color + + type-fest@1.4.0: {} + + type-fest@2.19.0: {} + + type-fest@3.13.1: {} + + typedarray-to-buffer@3.1.5: + dependencies: + is-typedarray: 1.0.0 + + unique-filename@2.0.1: + dependencies: + unique-slug: 3.0.0 + + unique-filename@3.0.0: + dependencies: + unique-slug: 4.0.0 + + unique-slug@3.0.0: + dependencies: + imurmurhash: 0.1.4 + + unique-slug@4.0.0: + dependencies: + imurmurhash: 0.1.4 + + unique-string@3.0.0: + dependencies: + crypto-random-string: 4.0.0 + + untildify@4.0.0: {} + + update-notifier@6.0.2: + dependencies: + boxen: 7.1.1 + chalk: 5.3.0 + configstore: 6.0.0 + has-yarn: 3.0.0 + import-lazy: 4.0.0 + is-ci: 3.0.1 + is-installed-globally: 0.4.0 + is-npm: 6.0.0 + is-yarn-global: 0.4.1 + latest-version: 7.0.0 + pupa: 3.1.0 + semver: 7.6.0 + semver-diff: 4.0.0 + xdg-basedir: 5.1.0 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + validate-npm-package-name@5.0.1: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@3.0.1: + dependencies: + isexe: 2.0.0 + + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + + widest-line@4.0.1: + dependencies: + string-width: 5.1.2 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.1.0 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + write-file-atomic@3.0.3: + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + + xdg-basedir@5.1.0: {} + + yallist@4.0.0: {} + + yaml@2.3.4: {} + + yocto-queue@0.1.0: {} diff --git a/script/DeployEchoCrossChain.s.sol b/script/DeployEchoCrossChain.s.sol index 1ba94eb..6ddaca3 100644 --- a/script/DeployEchoCrossChain.s.sol +++ b/script/DeployEchoCrossChain.s.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; -import "contracts/EchoCrossChain.sol"; import "forge-std/Script.sol"; +import "../src/EchoCrossChain.sol"; contract DeployEchoCrossChain is Script { // Exclude from coverage report @@ -10,12 +10,7 @@ contract DeployEchoCrossChain is Script { function run() external { vm.startBroadcast(); - new EchoCrossChain({ - owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), - wormhole: address(0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78), - chainId: 2, - wormholeFinality: 1 - }); + new EchoCrossChain({owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09)}); vm.stopBroadcast(); } diff --git a/script/TestEchoCrossChain.s.sol b/script/TestEchoCrossChain.s.sol deleted file mode 100644 index 279a618..0000000 --- a/script/TestEchoCrossChain.s.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "contracts/EchoCrossChain.sol"; -import "forge-std/Script.sol"; - -contract TestEchoCC is Script { - // Exclude from coverage report - function test() public {} - - function run() external { - vm.startBroadcast(); - - // Use existing contract - EchoCrossChain echo = EchoCrossChain(0x7DA16cd402106Adaf39092215DbB54092b80B6E6); - - echo.registerEmitter(1, bytes32("echoSolanaAddress")); - // echo.sendMessage('test'); - - vm.stopBroadcast(); - } -} diff --git a/src/EchoCrossChain.sol b/src/EchoCrossChain.sol index 070fa10..7d66aa2 100644 --- a/src/EchoCrossChain.sol +++ b/src/EchoCrossChain.sol @@ -1,21 +1,20 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/Admin.sol"; -import "contracts/Banker.sol"; -import "contracts/EchoError.sol"; -import "contracts/EchoState.sol"; -import "contracts/MessageValidator.sol"; -import "contracts/escrow/Escrow.sol"; -import "contracts/types/Offer.sol"; -import "contracts/wormhole/WormholeGovernance.sol"; import "solmate/utils/ReentrancyGuard.sol"; +import "./Admin.sol"; +import "./Banker.sol"; +import "./EchoState.sol"; +import "./escrow/Escrow.sol"; +import "./types/Offer.sol"; -contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGovernance, EchoState, MessageValidator { - constructor(address owner, address wormhole, uint16 chainId, uint8 wormholeFinality) - Admin(owner) - WormholeGovernance(wormhole, chainId, wormholeFinality) - {} +contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, EchoState { + // @dev For future use... + uint16 private chainId; + + constructor(address owner) Admin(owner) { + chainId = uint16(block.chainid); + } /** * Same chain offers @@ -26,7 +25,7 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover revert InvalidSender(); } _deposit(offer.senderItems, offer.sender); - _createOffer(offer, _state.chainId); + _createOffer(offer, chainId); } function acceptOffer(bytes32 offerId) external payable nonReentrant notPaused { @@ -75,12 +74,11 @@ contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, WormholeGover } // @dev This function assumes that the offer was created on another chain. - function acceptOffer(string calldata offerId, Offer calldata offer, bytes memory encodedMessage) - external - payable - nonReentrant - notPaused - { + function acceptOffer( + string calldata offerId, + Offer calldata offer, + bytes memory encodedMessage + ) external payable nonReentrant notPaused { // if (_offers[offerId].sender != address(0)) { // revert OfferAlreadyExist(); // } diff --git a/src/EchoState.sol b/src/EchoState.sol index 98695e6..121c393 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -142,7 +142,7 @@ abstract contract EchoState { delete offers[offerId]; } - modifier offerNotExpired(uint64 expiration) { + modifier offerNotExpired(uint256 expiration) { if (expiration <= block.timestamp) { revert OfferHasExpired(); } diff --git a/src/escrow/Escrow.sol b/src/escrow/Escrow.sol index e20f61b..d5565b7 100644 --- a/src/escrow/Escrow.sol +++ b/src/escrow/Escrow.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/escrow/EscrowHandler.sol"; -import "contracts/types/OfferItems.sol"; +import "./EscrowHandler.sol"; +import "../types/OfferItems.sol"; abstract contract Escrow is EscrowHandler { function _deposit(OfferItems memory offerItems, address from) internal { diff --git a/src/escrow/EscrowHandler.sol b/src/escrow/EscrowHandler.sol index 19a54c8..5fbe750 100644 --- a/src/escrow/EscrowHandler.sol +++ b/src/escrow/EscrowHandler.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; import "solmate/tokens/ERC721.sol"; -import "contracts/types/OfferItems.sol"; +import "../types/OfferItems.sol"; abstract contract EscrowHandler is ERC721TokenReceiver { function _transferERC721(address collectionAddress, uint256 id, address from, address to) internal { diff --git a/src/types/Offer.sol b/src/types/Offer.sol index f0fa062..de32f43 100644 --- a/src/types/Offer.sol +++ b/src/types/Offer.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/types/OfferItems.sol"; +import "./OfferItems.sol"; enum OfferState { OPEN, @@ -14,6 +14,6 @@ struct Offer { address receiver; OfferItems senderItems; OfferItems receiverItems; - uint64 expiration; + uint256 expiration; OfferState state; } diff --git a/src/types/OfferItems.sol b/src/types/OfferItems.sol index 9a85cc3..280ae61 100644 --- a/src/types/OfferItems.sol +++ b/src/types/OfferItems.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/types/OfferItem.sol"; +import "./OfferItem.sol"; // @dev Struct representing multiple offer items. We store the count for decoding purposes struct OfferItems { - uint16 chainId; + uint256 chainId; OfferItem[] items; } diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index d0ff33e..e2b9b8f 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -4,22 +4,17 @@ pragma solidity ^0.8.18; import "./mock/Mocked721.sol"; import "./mock/MockHandler.sol"; import "./mock/WormholeSimulator.sol"; -import "contracts/EchoCrossChain.sol"; -import "contracts/wormhole/IWormhole.sol"; import "forge-std/Test.sol"; +import "./utils/OfferUtils.sol"; +import "../src/EchoCrossChain.sol"; -abstract contract BaseTest is Test { +abstract contract BaseTest is Test, OfferUtils { // Exclude from coverage report function test() public {} - // guardian private key for simulated signing of Wormhole messages - uint256 guardianSigner; - - // contract instances - IWormhole wormhole; - WormholeSimulator wormholeSimulator; - EchoCrossChain public echo; + + // TODO Remove? // To test internal function as it's impossible to reach the code // from echo (echo also checks for length) MockedHandler public handler; @@ -50,8 +45,6 @@ abstract contract BaseTest is Test { address[] public counterparty721Collections; uint256[] public counterparty721Ids; - uint256 public in6hours; - function setUp() public { // Generate account2 and signer from private key. account2 = vm.addr(account2PrivateKey); @@ -63,28 +56,7 @@ abstract contract BaseTest is Test { vm.deal(account3, 100 ether); vm.deal(account4, 100 ether); - /* Initialize wormhole */ - // verify that we're using the correct fork (AVAX mainnet in this case) - require(block.chainid == vm.envUint("TESTING_AVAX_FORK_CHAINID"), "wrong evm"); - - // this will be used to sign Wormhole messages - guardianSigner = uint256(vm.envBytes32("TESTING_DEVNET_GUARDIAN")); - - // we may need to interact with Wormhole throughout the test - wormhole = IWormhole(vm.envAddress("TESTING_AVAX_WORMHOLE_ADDRESS")); - - // set up Wormhole using Wormhole existing on AVAX mainnet - wormholeSimulator = new SigningWormholeSimulator(wormhole, guardianSigner); - - // verify Wormhole state from fork - require(wormhole.chainId() == uint16(vm.envUint("TESTING_AVAX_WORMHOLE_CHAINID")), "wrong chainId"); - require(wormhole.messageFee() == vm.envUint("TESTING_AVAX_WORMHOLE_MESSAGE_FEE"), "wrong messageFee"); - require( - wormhole.getCurrentGuardianSetIndex() == uint32(vm.envUint("TESTING_AVAX_WORMHOLE_GUARDIAN_SET_INDEX")), - "wrong guardian set index" - ); - - echo = new EchoCrossChain(address(owner), address(wormhole), wormhole.chainId(), uint8(1)); + echo = new EchoCrossChain(address(owner)); handler = new MockedHandler(); apes = new Mocked721("Apes", "APE"); @@ -118,6 +90,34 @@ abstract contract BaseTest is Test { in6hours = block.timestamp + (60 * 60 * 6); } + function _createMockOffer() internal returns (Offer memory offer) { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + echo.createOffer(offer); + } + // @dev Method to execute a mock trade with predefined values // @dev Do not use this method if you expect a revert as the way Foundry is built, it won't catch the revert function _executeMockTrade(string memory id, address creator, address counter, uint256 fees) internal { diff --git a/test/CreateOffer.t.sol b/test/CreateOffer.t.sol new file mode 100644 index 0000000..772b181 --- /dev/null +++ b/test/CreateOffer.t.sol @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "./BaseTest.t.sol"; +import "forge-std/Test.sol"; +import "../src/types/OfferItems.sol"; +import "../src/types/Offer.sol"; + +contract CreateOfferTest is BaseTest { + function testCannotCreateOfferIfReceiverItemsIsEmpty() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](0); + uint256[] memory receiverTokenIds = new uint256[](0); + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.ACCEPTED + ); + + vm.prank(account1); + vm.expectRevert(InvalidAssets.selector); + echo.createOffer(offer); + } + + function testCannotCreateOfferIfSenderItemsIsEmpty() public { + address[] memory senderTokenAddresses = new address[](0); + uint256[] memory senderTokenIds = new uint256[](0); + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.ACCEPTED + ); + + vm.prank(account1); + vm.expectRevert(InvalidAssets.selector); + echo.createOffer(offer); + } + + function testCannotCreateOfferIfStateNotOpen() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.ACCEPTED + ); + + vm.prank(account1); + vm.expectRevert(InvalidOfferState.selector); + echo.createOffer(offer); + } + + function testCannotCreateOfferIfNotSender() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account2); + vm.expectRevert(InvalidSender.selector); + echo.createOffer(offer); + } + + function testCannotCreateDuplicateOffer() public { + Offer memory firstOffer = _createMockOffer(); + + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory secondOffer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(OfferAlreadyExist.selector); + echo.createOffer(secondOffer); + } + // Creating a same chain offer + + function testCanCreateOfferSingleAsset() public { + Offer memory offer = _createMockOffer(); + + // validate the offer id + bytes32 offerId = generateOfferId(offer); + ( + address sender, + address receiver, + OfferItems memory senderItems, + OfferItems memory receiverItems, + uint256 expiration, + OfferState state + ) = echo.offers(offerId); + assertOfferEq( + offer, + Offer({ + sender: sender, + receiver: receiver, + senderItems: senderItems, + receiverItems: receiverItems, + expiration: expiration, + state: state + }) + ); + + // validate that the sender items are in escrow + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + // validate that the receiver items are not in escrow + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + } +} diff --git a/test/Ownership.t.sol b/test/Ownership.t.sol index 4b33665..2dc96f5 100644 --- a/test/Ownership.t.sol +++ b/test/Ownership.t.sol @@ -6,84 +6,97 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract OwnershipTest is BaseTest { -// // Sender is not creator -// function testCannotExecuteTradeIfNotCreator() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// // Counterparty -// vm.prank(account2); -// vm.expectRevert(InvalidCreator.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Random account -// vm.prank(account3); -// vm.expectRevert(InvalidCreator.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -// -// // Creator is not owner -// function testCannotExecuteTradeIfCreatorNotOwner() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account3, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account3); -// vm.expectRevert(bytes("WRONG_FROM")); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -// -// // TODO Should be the same error message as the other? -// // Counterparty is not owner -// function testCannotExecuteTradeIfCounterpartyNotOwner() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird3Id); -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(bytes("WRONG_FROM")); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } + // Sender is not creator + function testCannotCreateOfferIfNotCreator() public { + senderItems.push(OfferItem({tokenAddress: apeAddress, tokenId: ape1Id})); + receiverItems.push(OfferItem({tokenAddress: birdAddress, tokenId: bird1Id})); + + Offer memory offer = Offer({ + sender: account1, + receiver: account2, + senderItems: OfferItems({chainId: block.chainid, items: senderItems}), + receiverItems: OfferItems({chainId: block.chainid, items: receiverItems}), + expiration: in6hours, + state: OfferState.OPEN + }); + } + // function testCannotExecuteTradeIfNotCreator() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // // Counterparty + // vm.prank(account2); + // vm.expectRevert(InvalidCreator.selector); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // + // // Random account + // vm.prank(account3); + // vm.expectRevert(InvalidCreator.selector); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // } + // + // // Creator is not owner + // function testCannotExecuteTradeIfCreatorNotOwner() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account3, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account3); + // vm.expectRevert(bytes("WRONG_FROM")); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // } + // + // // TODO Should be the same error message as the other? + // // Counterparty is not owner + // function testCannotExecuteTradeIfCounterpartyNotOwner() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird3Id); + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert(bytes("WRONG_FROM")); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // } } diff --git a/test/utils/OfferUtils.sol b/test/utils/OfferUtils.sol new file mode 100644 index 0000000..771f7d7 --- /dev/null +++ b/test/utils/OfferUtils.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; +import "../mock/Mocked721.sol"; +import "../../src/types/Offer.sol"; +import "../../src/types/OfferItem.sol"; +import "../../src/types/OfferItems.sol"; + +abstract contract OfferUtils is Test { + OfferItem[] public senderItems; + OfferItem[] public receiverItems; + + uint256 public in6hours; + + function generateOfferId(Offer memory offer) public pure returns (bytes32 offerId) { + // TODO Validate this behaviour + offerId = keccak256( + abi.encode( + offer.sender, + offer.receiver, + offer.senderItems.chainId, + keccak256(abi.encode(offer.senderItems.items)), // OfferItem[] + offer.receiverItems.chainId, + keccak256(abi.encode(offer.receiverItems.items)), // OfferItem[] + offer.expiration + ) + ); + } + + function generateOffer( + address sender, + address[] memory senderTokenAddresses, + uint256[] memory senderTokenIds, + uint256 senderChainId, + address receiver, + address[] memory receiverTokenAddresses, + uint256[] memory receiverTokenIds, + uint256 receiverChainId, + uint256 expiration, + OfferState state + ) public returns (Offer memory offer) { + require(senderTokenAddresses.length != senderTokenIds.length, "Sender items arrays do not match"); + + require(receiverTokenAddresses.length != receiverTokenIds.length, "Receiver items arrays do not match"); + + for (uint256 i = 0; i < senderTokenAddresses.length; i++) { + senderItems.push(OfferItem({tokenAddress: senderTokenAddresses[i], tokenId: senderTokenIds[i]})); + } + + for (uint256 i = 0; i < receiverTokenAddresses.length; i++) { + receiverItems.push(OfferItem({tokenAddress: receiverTokenAddresses[i], tokenId: receiverTokenIds[i]})); + } + + offer = Offer({ + sender: sender, + receiver: receiver, + senderItems: OfferItems({chainId: senderChainId, items: senderItems}), + receiverItems: OfferItems({chainId: receiverChainId, items: receiverItems}), + expiration: expiration, + state: state + }); + } + + function assertOfferItemsOwnership(OfferItem[] memory items, address owner) public { + for (uint256 i = 0; i < items.length; i++) { + Mocked721 tokenContract = Mocked721(items[i].tokenAddress); + assertEq(tokenContract.ownerOf(items[i].tokenId), owner); + } + } + + function assertOfferItemsEq(OfferItems memory items1, OfferItems memory items2) public { + assertEq(items1.items.length, items2.items.length); + assertEq(items1.chainId, items2.chainId); + for (uint256 i = 0; i < items1.items.length; i++) { + assertEq(items1.items[i].tokenAddress, items2.items[i].tokenAddress); + assertEq(items1.items[i].tokenId, items2.items[i].tokenId); + } + } + + function assertOfferEq(Offer memory offer1, Offer memory offer2) public { + assertEq(offer1.sender, offer2.sender); + assertOfferItemsEq(offer1.senderItems, offer2.senderItems); + assertEq(offer1.receiver, offer2.receiver); + assertOfferItemsEq(offer1.receiverItems, offer2.receiverItems); + assertEq(uint256(offer1.state), uint256(offer2.state)); + assertEq(offer1.expiration, offer2.expiration); + } +} From 784533fa912cf7d4b58468124dc986af7161bb08 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Fri, 10 May 2024 17:56:10 -0400 Subject: [PATCH 12/28] cleaned code and fixed tests --- foundry.toml | 3 +- {src => lib}/wormhole/BytesLib.sol | 0 {src => lib}/wormhole/IWormhole.sol | 0 package.json | 7 +- pnpm-lock.yaml | 3438 ++++++++++++--------------- src/EchoState.sol | 5 +- src/wormhole/Message.sol | 3 +- src/wormhole/WormholeGovernance.sol | 8 +- src/wormhole/WormholeState.sol | 4 +- test/Admin.t.sol | 70 - test/Banker.t.sol | 138 +- test/BaseTest.t.sol | 3 +- test/CreateOffer.t.sol | 69 +- test/mock/MockHandler.sol | 7 +- test/mock/MockWormhole.sol | 7 +- test/mock/WormholeSimulator.sol | 12 +- test/utils/OfferUtils.sol | 7 +- 17 files changed, 1668 insertions(+), 2113 deletions(-) rename {src => lib}/wormhole/BytesLib.sol (100%) rename {src => lib}/wormhole/IWormhole.sol (100%) diff --git a/foundry.toml b/foundry.toml index bcc25c6..e35a001 100644 --- a/foundry.toml +++ b/foundry.toml @@ -8,8 +8,7 @@ out = 'out' libs = ['lib'] remappings = [ - "forge-std/=lib/forge-std/src/", - "contracts/=src/", + "forge-std/=lib/forge-std/src/" ] fuzz_runs = 1000 diff --git a/src/wormhole/BytesLib.sol b/lib/wormhole/BytesLib.sol similarity index 100% rename from src/wormhole/BytesLib.sol rename to lib/wormhole/BytesLib.sol diff --git a/src/wormhole/IWormhole.sol b/lib/wormhole/IWormhole.sol similarity index 100% rename from src/wormhole/IWormhole.sol rename to lib/wormhole/IWormhole.sol diff --git a/package.json b/package.json index a2cfaf9..c2ad121 100644 --- a/package.json +++ b/package.json @@ -10,16 +10,15 @@ }, "scripts": { "build": "forge build", - "coverage": "forge coverage --report lcov", - "coverage:summary": "forge coverage --report summary", + "coverage": "forge coverage --match-path ./test/**/*.t.sol --report lcov", + "coverage:summary": "forge coverage --match-path ./test/**/*.t.sol --report summary", "prepare": "husky install", "pretty": "forge fmt", "modules:remove": "rm -rf node_modules; rm -rf pnpm-lock.yaml", "modules:update": "ncu -u --deep", "modules:update-minor": "ncu -u --deep --target=minor", "snapshot": "forge snapshot; cat .gas-snapshot", - "test": "forge test -vvv", - "test:bridge": "forge test --fork-url https://api.avax.network/ext/bc/C/rpc -vvv", + "test": "forge test --match-path ./test/**/*.t.sol -vvv", "test:gas-report": "forge test --gas-report" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1f6d10..0cab832 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,1573 +1,118 @@ -lockfileVersion: '9.0' +lockfileVersion: '6.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -importers: - - .: - devDependencies: - husky: - specifier: 9.0.11 - version: 9.0.11 - lint-staged: - specifier: 15.2.2 - version: 15.2.2 - npm-check-updates: - specifier: 16.14.20 - version: 16.14.20 - prettier: - specifier: 3.2.5 - version: 3.2.5 - prettier-plugin-solidity: - specifier: 1.3.1 - version: 1.3.1(prettier@3.2.5) - solhint: - specifier: 4.5.4 - version: 4.5.4 - solhint-plugin-prettier: - specifier: 0.1.0 - version: 0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5) +devDependencies: + husky: + specifier: 9.0.11 + version: 9.0.11 + lint-staged: + specifier: 15.2.2 + version: 15.2.2 + npm-check-updates: + specifier: 16.14.20 + version: 16.14.20 + prettier: + specifier: 3.2.5 + version: 3.2.5 + prettier-plugin-solidity: + specifier: 1.3.1 + version: 1.3.1(prettier@3.2.5) + solhint: + specifier: 4.5.4 + version: 4.5.4 + solhint-plugin-prettier: + specifier: 0.1.0 + version: 0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5) packages: - '@babel/code-frame@7.23.5': + /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.22.20': - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - - '@babel/highlight@7.23.4': - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} - engines: {node: '>=6.9.0'} - - '@colors/colors@1.5.0': - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} - - '@gar/promisify@1.1.3': - resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@npmcli/fs@2.1.2': - resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - '@npmcli/fs@3.1.1': - resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@npmcli/git@4.1.0': - resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@npmcli/installed-package-contents@2.1.0': - resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - - '@npmcli/move-file@2.0.1': - resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This functionality has been moved to @npmcli/fs - - '@npmcli/node-gyp@3.0.0': - resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@npmcli/promise-spawn@6.0.2': - resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@npmcli/run-script@6.0.2': - resolution: {integrity: sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - - '@pnpm/config.env-replace@1.1.0': - resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} - engines: {node: '>=12.22.0'} - - '@pnpm/network.ca-file@1.0.2': - resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} - engines: {node: '>=12.22.0'} - - '@pnpm/npm-conf@2.2.2': - resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} - engines: {node: '>=12'} - - '@prettier/sync@0.3.0': - resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} - peerDependencies: - prettier: ^3.0.0 - - '@sigstore/bundle@1.1.0': - resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@sigstore/protobuf-specs@0.2.1': - resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@sigstore/sign@1.0.0': - resolution: {integrity: sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@sigstore/tuf@1.0.3': - resolution: {integrity: sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@sindresorhus/is@5.6.0': - resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} - engines: {node: '>=14.16'} - - '@solidity-parser/parser@0.17.0': - resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} - - '@solidity-parser/parser@0.18.0': - resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} - - '@szmarczak/http-timer@5.0.1': - resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} - engines: {node: '>=14.16'} - - '@tootallnate/once@2.0.0': - resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} - engines: {node: '>= 10'} - - '@tufjs/canonical-json@1.0.0': - resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@tufjs/models@1.0.4': - resolution: {integrity: sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - '@types/http-cache-semantics@4.0.4': - resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} - - '@types/semver-utils@1.1.3': - resolution: {integrity: sha512-T+YwkslhsM+CeuhYUxyAjWm7mJ5am/K10UX40RuA6k6Lc7eGtq8iY2xOzy7Vq0GOqhl/xZl5l2FwURZMTPTUww==} - - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - - agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} - engines: {node: '>= 8.0.0'} - - aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - - ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - - ansi-escapes@6.2.0: - resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} - engines: {node: '>=14.16'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - - antlr4@4.13.1: - resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} - engines: {node: '>=16'} - - aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - - are-we-there-yet@3.0.1: - resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - - ast-parents@0.0.1: - resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} - - astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - boxen@7.1.1: - resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} - engines: {node: '>=14.16'} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - cacache@16.1.3: - resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - cacache@17.1.4: - resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - cacheable-lookup@7.0.0: - resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} - engines: {node: '>=14.16'} - - cacheable-request@10.2.14: - resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} - engines: {node: '>=14.16'} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - camelcase@7.0.1: - resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} - engines: {node: '>=14.16'} - - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - - chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - - clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - - cli-boxes@3.0.0: - resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} - engines: {node: '>=10'} - - cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} - engines: {node: 10.* || >= 12.*} - - cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} - - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - - commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - - commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - - configstore@6.0.0: - resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} - engines: {node: '>=12'} - - console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - - cosmiconfig@8.3.6: - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - - crypto-random-string@4.0.0: - resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} - engines: {node: '>=12'} - - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - - deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - - defer-to-connect@2.0.1: - resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} - engines: {node: '>=10'} - - delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - - dot-prop@6.0.1: - resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} - engines: {node: '>=10'} - - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - emoji-regex@10.3.0: - resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - - encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - - err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - - escape-goat@4.0.0: - resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} - engines: {node: '>=12'} - - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - - exponential-backoff@3.1.1: - resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-memoize@2.5.2: - resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} - - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - - form-data-encoder@2.1.4: - resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} - engines: {node: '>= 14.17'} - - fp-and-or@0.1.4: - resolution: {integrity: sha512-+yRYRhpnFPWXSly/6V4Lw9IfOV26uu30kynGJ03PW+MnjOEQe45RZ141QcS0aJehYBYA50GfCDnsRbFJdhssRw==} - engines: {node: '>=10'} - - fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - - fs-minipass@3.0.3: - resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - gauge@4.0.4: - resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - get-east-asian-width@1.2.0: - resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} - engines: {node: '>=18'} - - get-stdin@8.0.0: - resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} - engines: {node: '>=10'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - - glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - - global-dirs@3.0.1: - resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} - engines: {node: '>=10'} - - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - - got@12.6.1: - resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} - engines: {node: '>=14.16'} - - graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - - has-yarn@3.0.0: - resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - hosted-git-info@5.2.1: - resolution: {integrity: sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - hosted-git-info@6.1.1: - resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - - http-proxy-agent@5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} - - http2-wrapper@2.2.1: - resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} - engines: {node: '>=10.19.0'} - - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - - husky@9.0.11: - resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} - engines: {node: '>=18'} - hasBin: true - - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - - ignore-walk@6.0.5: - resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - import-lazy@4.0.0: - resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} - engines: {node: '>=8'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - infer-owner@1.0.4: - resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - - ini@2.0.0: - resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} - engines: {node: '>=10'} - - ini@4.1.2: - resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - is-ci@3.0.1: - resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} - hasBin: true - - is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - - is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} - engines: {node: '>=18'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-installed-globally@0.4.0: - resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} - engines: {node: '>=10'} - - is-lambda@1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - - is-npm@6.0.0: - resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - - is-yarn-global@0.4.1: - resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} - engines: {node: '>=12'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - - jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json-parse-even-better-errors@3.0.2: - resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - json-parse-helpfulerror@1.0.3: - resolution: {integrity: sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - jsonlines@0.1.1: - resolution: {integrity: sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==} - - jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - - latest-version@7.0.0: - resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} - engines: {node: '>=14.16'} - - lilconfig@3.0.0: - resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} - engines: {node: '>=14'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - lint-staged@15.2.2: - resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} - engines: {node: '>=18.12.0'} - hasBin: true - - listr2@8.0.1: - resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} - engines: {node: '>=18.0.0'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - log-update@6.0.0: - resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} - engines: {node: '>=18'} - - lowercase-keys@3.0.0: - resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - lru-cache@10.2.2: - resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} - engines: {node: 14 || >=16.14} - - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - - make-fetch-happen@10.2.1: - resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - make-fetch-happen@11.1.1: - resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - - mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - mimic-response@4.0.0: - resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - - minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - - minipass-fetch@2.1.2: - resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - minipass-fetch@3.0.5: - resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - - minipass-json-stream@1.0.1: - resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} - - minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - - minipass-sized@1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} - - minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - - minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - - minipass@7.1.0: - resolution: {integrity: sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==} - engines: {node: '>=16 || 14 >=14.17'} - - minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - - mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - - node-gyp@9.4.1: - resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} - engines: {node: ^12.13 || ^14.13 || >=16} - hasBin: true - - nopt@6.0.0: - resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - hasBin: true - - normalize-package-data@5.0.0: - resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - normalize-url@8.0.0: - resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} - engines: {node: '>=14.16'} - - npm-bundled@3.0.1: - resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-check-updates@16.14.20: - resolution: {integrity: sha512-sYbIhun4DrjO7NFOTdvs11nCar0etEhZTsEjL47eM0TuiGMhmYughRCxG2SpGRmGAQ7AkwN7bw2lWzoE7q6yOQ==} - engines: {node: '>=14.14'} - hasBin: true - - npm-install-checks@6.3.0: - resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-normalize-package-bin@3.0.1: - resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-package-arg@10.1.0: - resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-packlist@7.0.4: - resolution: {integrity: sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-pick-manifest@8.0.2: - resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-registry-fetch@14.0.5: - resolution: {integrity: sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - npmlog@6.0.2: - resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - - p-cancelable@3.0.0: - resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} - engines: {node: '>=12.20'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - - package-json@8.1.1: - resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} - engines: {node: '>=14.16'} - - pacote@15.2.0: - resolution: {integrity: sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse-github-url@1.0.2: - resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==} - engines: {node: '>=0.10.0'} - hasBin: true - - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - - path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} - - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - - pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - - prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - - prettier-plugin-solidity@1.3.1: - resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} - engines: {node: '>=16'} - peerDependencies: - prettier: '>=2.3.0' - - prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - - proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - - promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - - promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - - prompts-ncu@3.0.0: - resolution: {integrity: sha512-qyz9UxZ5MlPKWVhWrCmSZ1ahm2GVYdjLb8og2sg0IPth1KRuhcggHGuijz0e41dkx35p1t1q3GRISGH7QGALFA==} - engines: {node: '>= 14'} - - proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - pupa@3.1.0: - resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} - engines: {node: '>=12.20'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - quick-lru@5.1.1: - resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} - engines: {node: '>=10'} - - rc-config-loader@4.1.3: - resolution: {integrity: sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==} - - rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - - read-package-json-fast@3.0.2: - resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - read-package-json@6.0.4: - resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - registry-auth-token@5.0.2: - resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} - engines: {node: '>=14'} - - registry-url@6.0.1: - resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} - engines: {node: '>=12'} - - remote-git-tags@3.0.0: - resolution: {integrity: sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==} - engines: {node: '>=8'} - - require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - - resolve-alpn@1.2.1: - resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - responselike@3.0.0: - resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} - engines: {node: '>=14.16'} - - restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rfdc@1.3.1: - resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - - rimraf@5.0.5: - resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} - engines: {node: '>=14'} - hasBin: true - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - semver-diff@4.0.0: - resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} - engines: {node: '>=12'} - - semver-utils@1.1.4: - resolution: {integrity: sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==} - - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true - - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - - sigstore@1.9.0: - resolution: {integrity: sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - - slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} - - slice-ansi@7.1.0: - resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} - engines: {node: '>=18'} - - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - - socks-proxy-agent@7.0.0: - resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} - engines: {node: '>= 10'} - - socks@2.8.3: - resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - - solhint-plugin-prettier@0.1.0: - resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} - peerDependencies: - prettier: ^3.0.0 - prettier-plugin-solidity: ^1.0.0 - - solhint@4.5.4: - resolution: {integrity: sha512-Cu1XiJXub2q1eCr9kkJ9VPv1sGcmj3V7Zb76B0CoezDOB9bu3DxKIFFH7ggCl9fWpEPD6xBmRLfZrYijkVmujQ==} - hasBin: true - - solidity-comments-extractor@0.0.8: - resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} - - source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - spawn-please@2.0.2: - resolution: {integrity: sha512-KM8coezO6ISQ89c1BzyWNtcn2V2kAVtwIXd3cN/V5a0xPYc1F/vydrRc01wsKFEQ/p+V1a4sw4z2yMITIXrgGw==} - engines: {node: '>=14'} - - spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - - spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - - spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - - spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} - - sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - - ssri@10.0.6: - resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - ssri@9.0.1: - resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - - string-width@7.1.0: - resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} - engines: {node: '>=18'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - strip-json-comments@5.0.1: - resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} - engines: {node: '>=14.16'} - - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - table@6.8.1: - resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} - engines: {node: '>=10.0.0'} - - tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - tuf-js@1.1.7: - resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - type-fest@1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} - - type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - - type-fest@3.13.1: - resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} - engines: {node: '>=14.16'} - - typedarray-to-buffer@3.1.5: - resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - - unique-filename@2.0.1: - resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - unique-filename@3.0.0: - resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - unique-slug@3.0.0: - resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - unique-slug@4.0.0: - resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - unique-string@3.0.0: - resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} - engines: {node: '>=12'} - - untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - - update-notifier@6.0.2: - resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} - engines: {node: '>=14.16'} - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - - validate-npm-package-name@5.0.1: - resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - - wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - - widest-line@4.0.1: - resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} - engines: {node: '>=12'} - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - - wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - write-file-atomic@3.0.3: - resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} - - xdg-basedir@5.1.0: - resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} - engines: {node: '>=12'} - - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} - engines: {node: '>= 14'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@babel/code-frame@7.23.5': dependencies: '@babel/highlight': 7.23.4 chalk: 2.4.2 + dev: true - '@babel/helper-validator-identifier@7.22.20': {} + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true - '@babel/highlight@7.23.4': + /@babel/highlight@7.23.4: + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} dependencies: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 + dev: true - '@colors/colors@1.5.0': + /@colors/colors@1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true optional: true - '@gar/promisify@1.1.3': {} + /@gar/promisify@1.1.3: + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + dev: true - '@isaacs/cliui@8.0.2': + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} dependencies: string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 + string-width-cjs: /string-width@4.2.3 strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 + strip-ansi-cjs: /strip-ansi@6.0.1 wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true - '@nodelib/fs.scandir@2.1.5': + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 + dev: true - '@nodelib/fs.stat@2.0.5': {} + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true - '@nodelib/fs.walk@1.2.8': + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + dev: true - '@npmcli/fs@2.1.2': + /@npmcli/fs@2.1.2: + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: '@gar/promisify': 1.1.3 semver: 7.6.0 + dev: true - '@npmcli/fs@3.1.1': + /@npmcli/fs@3.1.1: + resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: semver: 7.6.0 + dev: true - '@npmcli/git@4.1.0': + /@npmcli/git@4.1.0: + resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: '@npmcli/promise-spawn': 6.0.2 lru-cache: 7.18.3 @@ -1579,24 +124,41 @@ snapshots: which: 3.0.1 transitivePeerDependencies: - bluebird + dev: true - '@npmcli/installed-package-contents@2.1.0': + /@npmcli/installed-package-contents@2.1.0: + resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true dependencies: npm-bundled: 3.0.1 npm-normalize-package-bin: 3.0.1 + dev: true - '@npmcli/move-file@2.0.1': + /@npmcli/move-file@2.0.1: + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs dependencies: mkdirp: 1.0.4 rimraf: 3.0.2 + dev: true - '@npmcli/node-gyp@3.0.0': {} + /@npmcli/node-gyp@3.0.0: + resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true - '@npmcli/promise-spawn@6.0.2': + /@npmcli/promise-spawn@6.0.2: + resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: which: 3.0.1 + dev: true - '@npmcli/run-script@6.0.2': + /@npmcli/run-script@6.0.2: + resolution: {integrity: sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: '@npmcli/node-gyp': 3.0.0 '@npmcli/promise-spawn': 6.0.2 @@ -1606,143 +168,253 @@ snapshots: transitivePeerDependencies: - bluebird - supports-color + dev: true - '@pkgjs/parseargs@0.11.0': + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true optional: true - '@pnpm/config.env-replace@1.1.0': {} + /@pnpm/config.env-replace@1.1.0: + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + dev: true - '@pnpm/network.ca-file@1.0.2': + /@pnpm/network.ca-file@1.0.2: + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} dependencies: graceful-fs: 4.2.10 + dev: true - '@pnpm/npm-conf@2.2.2': + /@pnpm/npm-conf@2.2.2: + resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} + engines: {node: '>=12'} dependencies: '@pnpm/config.env-replace': 1.1.0 '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 + dev: true - '@prettier/sync@0.3.0(prettier@3.2.5)': + /@prettier/sync@0.3.0(prettier@3.2.5): + resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} + peerDependencies: + prettier: ^3.0.0 dependencies: prettier: 3.2.5 + dev: true - '@sigstore/bundle@1.1.0': + /@sigstore/bundle@1.1.0: + resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: '@sigstore/protobuf-specs': 0.2.1 + dev: true - '@sigstore/protobuf-specs@0.2.1': {} + /@sigstore/protobuf-specs@0.2.1: + resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true - '@sigstore/sign@1.0.0': + /@sigstore/sign@1.0.0: + resolution: {integrity: sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: '@sigstore/bundle': 1.1.0 '@sigstore/protobuf-specs': 0.2.1 make-fetch-happen: 11.1.1 transitivePeerDependencies: - supports-color + dev: true - '@sigstore/tuf@1.0.3': + /@sigstore/tuf@1.0.3: + resolution: {integrity: sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: '@sigstore/protobuf-specs': 0.2.1 tuf-js: 1.1.7 transitivePeerDependencies: - supports-color + dev: true - '@sindresorhus/is@5.6.0': {} + /@sindresorhus/is@5.6.0: + resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} + engines: {node: '>=14.16'} + dev: true - '@solidity-parser/parser@0.17.0': {} + /@solidity-parser/parser@0.17.0: + resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} + dev: true - '@solidity-parser/parser@0.18.0': {} + /@solidity-parser/parser@0.18.0: + resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} + dev: true - '@szmarczak/http-timer@5.0.1': + /@szmarczak/http-timer@5.0.1: + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} dependencies: defer-to-connect: 2.0.1 + dev: true - '@tootallnate/once@2.0.0': {} + /@tootallnate/once@2.0.0: + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + dev: true - '@tufjs/canonical-json@1.0.0': {} + /@tufjs/canonical-json@1.0.0: + resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true - '@tufjs/models@1.0.4': + /@tufjs/models@1.0.4: + resolution: {integrity: sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: '@tufjs/canonical-json': 1.0.0 minimatch: 9.0.4 + dev: true - '@types/http-cache-semantics@4.0.4': {} + /@types/http-cache-semantics@4.0.4: + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + dev: true - '@types/semver-utils@1.1.3': {} + /@types/semver-utils@1.1.3: + resolution: {integrity: sha512-T+YwkslhsM+CeuhYUxyAjWm7mJ5am/K10UX40RuA6k6Lc7eGtq8iY2xOzy7Vq0GOqhl/xZl5l2FwURZMTPTUww==} + dev: true - abbrev@1.1.1: {} + /abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: true - agent-base@6.0.2: + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} dependencies: debug: 4.3.4 transitivePeerDependencies: - supports-color + dev: true - agentkeepalive@4.5.0: + /agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} dependencies: humanize-ms: 1.2.1 + dev: true - aggregate-error@3.1.0: + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 + dev: true - ajv@6.12.6: + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 + dev: true - ajv@8.12.0: + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 uri-js: 4.4.1 + dev: true - ansi-align@3.0.1: + /ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} dependencies: string-width: 4.2.3 + dev: true - ansi-escapes@6.2.0: + /ansi-escapes@6.2.0: + resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} + engines: {node: '>=14.16'} dependencies: type-fest: 3.13.1 + dev: true - ansi-regex@5.0.1: {} + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true - ansi-regex@6.0.1: {} + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true - ansi-styles@3.2.1: + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} dependencies: color-convert: 1.9.3 + dev: true - ansi-styles@4.3.0: + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} dependencies: color-convert: 2.0.1 + dev: true - ansi-styles@6.2.1: {} + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true - antlr4@4.13.1: {} + /antlr4@4.13.1: + resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} + engines: {node: '>=16'} + dev: true - aproba@2.0.0: {} + /aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: true - are-we-there-yet@3.0.1: + /are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: delegates: 1.0.0 readable-stream: 3.6.2 + dev: true - argparse@2.0.1: {} + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true - array-union@2.1.0: {} + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true - ast-parents@0.0.1: {} + /ast-parents@0.0.1: + resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} + dev: true - astral-regex@2.0.0: {} + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true - balanced-match@1.0.2: {} + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true - boxen@7.1.1: + /boxen@7.1.1: + resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} + engines: {node: '>=14.16'} dependencies: ansi-align: 3.0.1 camelcase: 7.0.1 @@ -1752,23 +424,35 @@ snapshots: type-fest: 2.19.0 widest-line: 4.0.1 wrap-ansi: 8.1.0 + dev: true - brace-expansion@1.1.11: + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 + dev: true - brace-expansion@2.0.1: + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: balanced-match: 1.0.2 + dev: true - braces@3.0.2: + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} dependencies: fill-range: 7.0.1 + dev: true - buffer-from@1.1.2: {} + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true - cacache@16.1.3: + /cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: '@npmcli/fs': 2.1.2 '@npmcli/move-file': 2.0.1 @@ -1790,14 +474,17 @@ snapshots: unique-filename: 2.0.1 transitivePeerDependencies: - bluebird + dev: true - cacache@17.1.4: + /cacache@17.1.4: + resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: '@npmcli/fs': 3.1.1 fs-minipass: 3.0.3 - glob: 10.3.12 + glob: 10.3.14 lru-cache: 7.18.3 - minipass: 7.1.0 + minipass: 7.1.1 minipass-collect: 1.0.2 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 @@ -1805,10 +492,16 @@ snapshots: ssri: 10.0.6 tar: 6.2.1 unique-filename: 3.0.0 + dev: true - cacheable-lookup@7.0.0: {} + /cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + dev: true - cacheable-request@10.2.14: + /cacheable-request@10.2.14: + resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} + engines: {node: '>=14.16'} dependencies: '@types/http-cache-semantics': 4.0.4 get-stream: 6.0.1 @@ -1817,151 +510,284 @@ snapshots: mimic-response: 4.0.0 normalize-url: 8.0.0 responselike: 3.0.0 + dev: true - callsites@3.1.0: {} + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true - camelcase@7.0.1: {} + /camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + dev: true - chalk@2.4.2: + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} dependencies: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 + dev: true - chalk@4.1.2: + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 + dev: true - chalk@5.3.0: {} + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true - chownr@2.0.0: {} + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: true - ci-info@3.9.0: {} + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: true - clean-stack@2.2.0: {} + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true - cli-boxes@3.0.0: {} + /cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + dev: true - cli-cursor@4.0.0: + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: restore-cursor: 4.0.0 + dev: true - cli-table3@0.6.4: + /cli-table3@0.6.4: + resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + engines: {node: 10.* || >= 12.*} dependencies: string-width: 4.2.3 optionalDependencies: '@colors/colors': 1.5.0 + dev: true - cli-truncate@4.0.0: + /cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} dependencies: slice-ansi: 5.0.0 string-width: 7.1.0 + dev: true - color-convert@1.9.3: + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: color-name: 1.1.3 + dev: true - color-convert@2.0.1: + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 + dev: true - color-name@1.1.3: {} + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true - color-name@1.1.4: {} + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true - color-support@1.1.3: {} + /color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: true - colorette@2.0.20: {} + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true - commander@10.0.1: {} + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: true - commander@11.1.0: {} + /commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: true - concat-map@0.0.1: {} + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true - config-chain@1.1.13: + /config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} dependencies: ini: 1.3.8 proto-list: 1.2.4 + dev: true - configstore@6.0.0: + /configstore@6.0.0: + resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} + engines: {node: '>=12'} dependencies: dot-prop: 6.0.1 graceful-fs: 4.2.10 unique-string: 3.0.0 write-file-atomic: 3.0.3 xdg-basedir: 5.1.0 + dev: true - console-control-strings@1.1.0: {} + /console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: true - cosmiconfig@8.3.6: + /cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 + dev: true - cross-spawn@7.0.3: + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + dev: true - crypto-random-string@4.0.0: + /crypto-random-string@4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} dependencies: type-fest: 1.4.0 + dev: true - debug@4.3.4: + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.1.2 + dev: true - decompress-response@6.0.0: + /decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} dependencies: mimic-response: 3.1.0 + dev: true - deep-extend@0.6.0: {} + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true - defer-to-connect@2.0.1: {} + /defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + dev: true - delegates@1.0.0: {} + /delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: true - dir-glob@3.0.1: + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} dependencies: path-type: 4.0.0 + dev: true - dot-prop@6.0.1: + /dot-prop@6.0.1: + resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} + engines: {node: '>=10'} dependencies: is-obj: 2.0.0 + dev: true - eastasianwidth@0.2.0: {} + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true - emoji-regex@10.3.0: {} + /emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + dev: true - emoji-regex@8.0.0: {} + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true - emoji-regex@9.2.2: {} + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true - encoding@0.1.13: + /encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + requiresBuild: true dependencies: iconv-lite: 0.6.3 + dev: true optional: true - env-paths@2.2.1: {} + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true - err-code@2.0.3: {} + /err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + dev: true - error-ex@1.3.2: + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: is-arrayish: 0.2.1 + dev: true - escape-goat@4.0.0: {} + /escape-goat@4.0.0: + resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} + engines: {node: '>=12'} + dev: true - escape-string-regexp@1.0.5: {} + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true - eventemitter3@5.0.1: {} + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: true - execa@8.0.1: + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} dependencies: cross-spawn: 7.0.3 get-stream: 8.0.1 @@ -1972,60 +798,103 @@ snapshots: onetime: 6.0.0 signal-exit: 4.1.0 strip-final-newline: 3.0.0 + dev: true - exponential-backoff@3.1.1: {} + /exponential-backoff@3.1.1: + resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + dev: true - fast-deep-equal@3.1.3: {} + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true - fast-diff@1.3.0: {} + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true - fast-glob@3.3.2: + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 + dev: true - fast-json-stable-stringify@2.1.0: {} + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true - fast-memoize@2.5.2: {} + /fast-memoize@2.5.2: + resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} + dev: true - fastq@1.17.1: + /fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} dependencies: reusify: 1.0.4 + dev: true - fill-range@7.0.1: + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 + dev: true - find-up@5.0.0: + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} dependencies: locate-path: 6.0.0 path-exists: 4.0.0 + dev: true - foreground-child@3.1.1: + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 + dev: true - form-data-encoder@2.1.4: {} + /form-data-encoder@2.1.4: + resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} + engines: {node: '>= 14.17'} + dev: true - fp-and-or@0.1.4: {} + /fp-and-or@0.1.4: + resolution: {integrity: sha512-+yRYRhpnFPWXSly/6V4Lw9IfOV26uu30kynGJ03PW+MnjOEQe45RZ141QcS0aJehYBYA50GfCDnsRbFJdhssRw==} + engines: {node: '>=10'} + dev: true - fs-minipass@2.1.0: + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} dependencies: minipass: 3.3.6 + dev: true - fs-minipass@3.0.3: + /fs-minipass@3.0.3: + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - minipass: 7.1.0 + minipass: 7.1.1 + dev: true - fs.realpath@1.0.0: {} + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true - function-bind@1.1.2: {} + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true - gauge@4.0.4: + /gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: aproba: 2.0.0 color-support: 1.1.3 @@ -2035,28 +904,49 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 wide-align: 1.1.5 + dev: true - get-east-asian-width@1.2.0: {} + /get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + dev: true - get-stdin@8.0.0: {} + /get-stdin@8.0.0: + resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} + engines: {node: '>=10'} + dev: true - get-stream@6.0.1: {} + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true - get-stream@8.0.1: {} + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true - glob-parent@5.1.2: + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 + dev: true - glob@10.3.12: + /glob@10.3.14: + resolution: {integrity: sha512-4fkAqu93xe9Mk7le9v0y3VrPDqLKHarNi2s4Pv7f2yOvfhWfhc7hRPHC/JyqMqb8B/Dt/eGS4n7ykwf3fOsl8g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 minimatch: 9.0.4 - minipass: 7.1.0 - path-scurry: 1.10.2 + minipass: 7.1.1 + path-scurry: 1.11.0 + dev: true - glob@7.2.3: + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -2064,20 +954,29 @@ snapshots: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 + dev: true - glob@8.1.0: + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 minimatch: 5.1.6 once: 1.4.0 + dev: true - global-dirs@3.0.1: + /global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} dependencies: ini: 2.0.0 + dev: true - globby@11.1.0: + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} dependencies: array-union: 2.1.0 dir-glob: 3.0.1 @@ -2085,8 +984,11 @@ snapshots: ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 + dev: true - got@12.6.1: + /got@12.6.1: + resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} + engines: {node: '>=14.16'} dependencies: '@sindresorhus/is': 5.6.0 '@szmarczak/http-timer': 5.0.1 @@ -2099,199 +1001,380 @@ snapshots: lowercase-keys: 3.0.0 p-cancelable: 3.0.0 responselike: 3.0.0 + dev: true - graceful-fs@4.2.10: {} + /graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true - has-flag@3.0.0: {} + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true - has-flag@4.0.0: {} + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true - has-unicode@2.0.1: {} + /has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: true - has-yarn@3.0.0: {} + /has-yarn@3.0.0: + resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true - hasown@2.0.2: + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 + dev: true - hosted-git-info@5.2.1: + /hosted-git-info@5.2.1: + resolution: {integrity: sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: lru-cache: 7.18.3 + dev: true - hosted-git-info@6.1.1: + /hosted-git-info@6.1.1: + resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: lru-cache: 7.18.3 + dev: true - http-cache-semantics@4.1.1: {} + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: true - http-proxy-agent@5.0.0: + /http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 debug: 4.3.4 transitivePeerDependencies: - supports-color + dev: true - http2-wrapper@2.2.1: + /http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} dependencies: quick-lru: 5.1.1 resolve-alpn: 1.2.1 + dev: true - https-proxy-agent@5.0.1: + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 debug: 4.3.4 transitivePeerDependencies: - supports-color + dev: true - human-signals@5.0.0: {} + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true - humanize-ms@1.2.1: + /humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} dependencies: ms: 2.1.2 + dev: true - husky@9.0.11: {} + /husky@9.0.11: + resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} + engines: {node: '>=18'} + hasBin: true + dev: true - iconv-lite@0.6.3: + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + requiresBuild: true dependencies: safer-buffer: 2.1.2 + dev: true optional: true - ignore-walk@6.0.5: + /ignore-walk@6.0.5: + resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: minimatch: 9.0.4 + dev: true - ignore@5.3.1: {} + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true - import-fresh@3.3.0: + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 + dev: true - import-lazy@4.0.0: {} + /import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + dev: true - imurmurhash@0.1.4: {} + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true - indent-string@4.0.0: {} + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true - infer-owner@1.0.4: {} + /infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + dev: true - inflight@1.0.6: + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: once: 1.4.0 wrappy: 1.0.2 + dev: true - inherits@2.0.4: {} + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true - ini@1.3.8: {} + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true - ini@2.0.0: {} + /ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + dev: true - ini@4.1.2: {} + /ini@4.1.2: + resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true - ip-address@9.0.5: + /ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} dependencies: jsbn: 1.1.0 sprintf-js: 1.1.3 + dev: true - is-arrayish@0.2.1: {} + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true - is-ci@3.0.1: + /is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true dependencies: ci-info: 3.9.0 + dev: true - is-core-module@2.13.1: + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: hasown: 2.0.2 + dev: true - is-extglob@2.1.1: {} + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true - is-fullwidth-code-point@3.0.0: {} + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true - is-fullwidth-code-point@4.0.0: {} + /is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true - is-fullwidth-code-point@5.0.0: + /is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} dependencies: get-east-asian-width: 1.2.0 + dev: true - is-glob@4.0.3: + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 + dev: true - is-installed-globally@0.4.0: + /is-installed-globally@0.4.0: + resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} + engines: {node: '>=10'} dependencies: global-dirs: 3.0.1 is-path-inside: 3.0.3 + dev: true - is-lambda@1.0.1: {} + /is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + dev: true - is-npm@6.0.0: {} + /is-npm@6.0.0: + resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true - is-number@7.0.0: {} + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true - is-obj@2.0.0: {} + /is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + dev: true - is-path-inside@3.0.3: {} + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true - is-stream@3.0.0: {} + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true - is-typedarray@1.0.0: {} + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true - is-yarn-global@0.4.1: {} + /is-yarn-global@0.4.1: + resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} + engines: {node: '>=12'} + dev: true - isexe@2.0.0: {} + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true - jackspeak@2.3.6: + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 + dev: true - jju@1.4.0: {} + /jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + dev: true - js-tokens@4.0.0: {} + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true - js-yaml@4.1.0: + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true dependencies: argparse: 2.0.1 + dev: true - jsbn@1.1.0: {} + /jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + dev: true - json-buffer@3.0.1: {} + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true - json-parse-even-better-errors@2.3.1: {} + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true - json-parse-even-better-errors@3.0.2: {} + /json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true - json-parse-helpfulerror@1.0.3: + /json-parse-helpfulerror@1.0.3: + resolution: {integrity: sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==} dependencies: jju: 1.4.0 + dev: true - json-schema-traverse@0.4.1: {} + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true - json-schema-traverse@1.0.0: {} + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true - json5@2.2.3: {} + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true - jsonlines@0.1.1: {} + /jsonlines@0.1.1: + resolution: {integrity: sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==} + dev: true - jsonparse@1.3.1: {} + /jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: true - keyv@4.5.4: + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: json-buffer: 3.0.1 + dev: true - kleur@4.1.5: {} + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: true - latest-version@7.0.0: + /latest-version@7.0.0: + resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} + engines: {node: '>=14.16'} dependencies: package-json: 8.1.1 + dev: true - lilconfig@3.0.0: {} + /lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + engines: {node: '>=14'} + dev: true - lines-and-columns@1.2.4: {} + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true - lint-staged@15.2.2: + /lint-staged@15.2.2: + resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} + engines: {node: '>=18.12.0'} + hasBin: true dependencies: chalk: 5.3.0 commander: 11.1.0 @@ -2305,8 +1388,11 @@ snapshots: yaml: 2.3.4 transitivePeerDependencies: - supports-color + dev: true - listr2@8.0.1: + /listr2@8.0.1: + resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} + engines: {node: '>=18.0.0'} dependencies: cli-truncate: 4.0.0 colorette: 2.0.20 @@ -2314,34 +1400,59 @@ snapshots: log-update: 6.0.0 rfdc: 1.3.1 wrap-ansi: 9.0.0 + dev: true - locate-path@6.0.0: + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} dependencies: p-locate: 5.0.0 + dev: true - lodash.truncate@4.4.2: {} + /lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + dev: true - lodash@4.17.21: {} + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true - log-update@6.0.0: + /log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} dependencies: ansi-escapes: 6.2.0 cli-cursor: 4.0.0 slice-ansi: 7.1.0 strip-ansi: 7.1.0 wrap-ansi: 9.0.0 + dev: true - lowercase-keys@3.0.0: {} + /lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true - lru-cache@10.2.2: {} + /lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + dev: true - lru-cache@6.0.0: + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} dependencies: yallist: 4.0.0 + dev: true - lru-cache@7.18.3: {} + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: true - make-fetch-happen@10.2.1: + /make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: agentkeepalive: 4.5.0 cacache: 16.1.3 @@ -2362,8 +1473,11 @@ snapshots: transitivePeerDependencies: - bluebird - supports-color + dev: true - make-fetch-happen@11.1.1: + /make-fetch-happen@11.1.1: + resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: agentkeepalive: 4.5.0 cacache: 17.1.4 @@ -2382,95 +1496,170 @@ snapshots: ssri: 10.0.6 transitivePeerDependencies: - supports-color + dev: true - merge-stream@2.0.0: {} + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true - merge2@1.4.1: {} + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true - micromatch@4.0.5: + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} dependencies: braces: 3.0.2 picomatch: 2.3.1 + dev: true - mimic-fn@2.1.0: {} + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true - mimic-fn@4.0.0: {} + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true - mimic-response@3.1.0: {} + /mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: true - mimic-response@4.0.0: {} + /mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true - minimatch@3.1.2: + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 + dev: true - minimatch@5.1.6: + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 + dev: true - minimatch@9.0.4: + /minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 + dev: true - minimist@1.2.8: {} + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true - minipass-collect@1.0.2: + /minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} dependencies: minipass: 3.3.6 + dev: true - minipass-fetch@2.1.2: + /minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: minipass: 3.3.6 minipass-sized: 1.0.3 minizlib: 2.1.2 optionalDependencies: encoding: 0.1.13 + dev: true - minipass-fetch@3.0.5: + /minipass-fetch@3.0.5: + resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - minipass: 7.1.0 + minipass: 7.1.1 minipass-sized: 1.0.3 minizlib: 2.1.2 optionalDependencies: encoding: 0.1.13 + dev: true - minipass-flush@1.0.5: + /minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} dependencies: minipass: 3.3.6 + dev: true - minipass-json-stream@1.0.1: + /minipass-json-stream@1.0.1: + resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} dependencies: jsonparse: 1.3.1 minipass: 3.3.6 + dev: true - minipass-pipeline@1.2.4: + /minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} dependencies: minipass: 3.3.6 + dev: true - minipass-sized@1.0.3: + /minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} dependencies: minipass: 3.3.6 + dev: true - minipass@3.3.6: + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} dependencies: yallist: 4.0.0 + dev: true - minipass@5.0.0: {} + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: true - minipass@7.1.0: {} + /minipass@7.1.1: + resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true - minizlib@2.1.2: + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} dependencies: minipass: 3.3.6 yallist: 4.0.0 + dev: true - mkdirp@1.0.4: {} + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true - ms@2.1.2: {} + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true - negotiator@0.6.3: {} + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: true - node-gyp@9.4.1: + /node-gyp@9.4.1: + resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} + engines: {node: ^12.13 || ^14.13 || >=16} + hasBin: true dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.1 @@ -2486,25 +1675,42 @@ snapshots: transitivePeerDependencies: - bluebird - supports-color + dev: true - nopt@6.0.0: + /nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true dependencies: abbrev: 1.1.1 + dev: true - normalize-package-data@5.0.0: + /normalize-package-data@5.0.0: + resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: hosted-git-info: 6.1.1 is-core-module: 2.13.1 semver: 7.6.0 validate-npm-package-license: 3.0.4 + dev: true - normalize-url@8.0.0: {} + /normalize-url@8.0.0: + resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} + engines: {node: '>=14.16'} + dev: true - npm-bundled@3.0.1: + /npm-bundled@3.0.1: + resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: npm-normalize-package-bin: 3.0.1 + dev: true - npm-check-updates@16.14.20: + /npm-check-updates@16.14.20: + resolution: {integrity: sha512-sYbIhun4DrjO7NFOTdvs11nCar0etEhZTsEjL47eM0TuiGMhmYughRCxG2SpGRmGAQ7AkwN7bw2lWzoE7q6yOQ==} + engines: {node: '>=14.14'} + hasBin: true dependencies: '@types/semver-utils': 1.1.3 chalk: 5.3.0 @@ -2530,7 +1736,7 @@ snapshots: prompts-ncu: 3.0.0 rc-config-loader: 4.1.3 remote-git-tags: 3.0.0 - rimraf: 5.0.5 + rimraf: 5.0.6 semver: 7.6.0 semver-utils: 1.1.4 source-map-support: 0.5.21 @@ -2542,32 +1748,50 @@ snapshots: transitivePeerDependencies: - bluebird - supports-color + dev: true - npm-install-checks@6.3.0: + /npm-install-checks@6.3.0: + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: semver: 7.6.0 + dev: true - npm-normalize-package-bin@3.0.1: {} + /npm-normalize-package-bin@3.0.1: + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true - npm-package-arg@10.1.0: + /npm-package-arg@10.1.0: + resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: hosted-git-info: 6.1.1 proc-log: 3.0.0 semver: 7.6.0 validate-npm-package-name: 5.0.1 + dev: true - npm-packlist@7.0.4: + /npm-packlist@7.0.4: + resolution: {integrity: sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: ignore-walk: 6.0.5 + dev: true - npm-pick-manifest@8.0.2: + /npm-pick-manifest@8.0.2: + resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: npm-install-checks: 6.3.0 npm-normalize-package-bin: 3.0.1 npm-package-arg: 10.1.0 semver: 7.6.0 + dev: true - npm-registry-fetch@14.0.5: + /npm-registry-fetch@14.0.5: + resolution: {integrity: sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: make-fetch-happen: 11.1.1 minipass: 5.0.0 @@ -2578,52 +1802,85 @@ snapshots: proc-log: 3.0.0 transitivePeerDependencies: - supports-color + dev: true - npm-run-path@5.3.0: + /npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: path-key: 4.0.0 + dev: true - npmlog@6.0.2: + /npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: are-we-there-yet: 3.0.1 console-control-strings: 1.1.0 gauge: 4.0.4 set-blocking: 2.0.0 + dev: true - once@1.4.0: + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 + dev: true - onetime@5.1.2: + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} dependencies: mimic-fn: 2.1.0 + dev: true - onetime@6.0.0: + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} dependencies: mimic-fn: 4.0.0 + dev: true - p-cancelable@3.0.0: {} + /p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} + dev: true - p-limit@3.1.0: + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} dependencies: yocto-queue: 0.1.0 + dev: true - p-locate@5.0.0: + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} dependencies: p-limit: 3.1.0 + dev: true - p-map@4.0.0: + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} dependencies: aggregate-error: 3.1.0 + dev: true - package-json@8.1.1: + /package-json@8.1.1: + resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} + engines: {node: '>=14.16'} dependencies: got: 12.6.1 registry-auth-token: 5.0.2 registry-url: 6.0.1 semver: 7.6.0 + dev: true - pacote@15.2.0: + /pacote@15.2.0: + resolution: {integrity: sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true dependencies: '@npmcli/git': 4.1.0 '@npmcli/installed-package-contents': 2.1.0 @@ -2646,86 +1903,175 @@ snapshots: transitivePeerDependencies: - bluebird - supports-color + dev: true - parent-module@1.0.1: + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} dependencies: callsites: 3.1.0 + dev: true - parse-github-url@1.0.2: {} + /parse-github-url@1.0.2: + resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==} + engines: {node: '>=0.10.0'} + hasBin: true + dev: true - parse-json@5.2.0: + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} dependencies: '@babel/code-frame': 7.23.5 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + dev: true - path-exists@4.0.0: {} + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true - path-is-absolute@1.0.1: {} + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true - path-key@3.1.1: {} + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true - path-key@4.0.0: {} + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true - path-scurry@1.10.2: + /path-scurry@1.11.0: + resolution: {integrity: sha512-LNHTaVkzaYaLGlO+0u3rQTz7QrHTFOuKyba9JMTQutkmtNew8dw8wOD7mTU/5fCPZzCWpfW0XnQKzY61P0aTaw==} + engines: {node: '>=16 || 14 >=14.17'} dependencies: lru-cache: 10.2.2 - minipass: 7.1.0 + minipass: 7.1.1 + dev: true - path-type@4.0.0: {} + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true - picomatch@2.3.1: {} + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true - pidtree@0.6.0: {} + /pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + dev: true - pluralize@8.0.0: {} + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: true - prettier-linter-helpers@1.0.0: + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} dependencies: fast-diff: 1.3.0 + dev: true - prettier-plugin-solidity@1.3.1(prettier@3.2.5): + /prettier-plugin-solidity@1.3.1(prettier@3.2.5): + resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} + engines: {node: '>=16'} + peerDependencies: + prettier: '>=2.3.0' dependencies: '@solidity-parser/parser': 0.17.0 prettier: 3.2.5 semver: 7.6.0 solidity-comments-extractor: 0.0.8 + dev: true - prettier@2.8.8: + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + requiresBuild: true + dev: true optional: true - prettier@3.2.5: {} + /prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + dev: true - proc-log@3.0.0: {} + /proc-log@3.0.0: + resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true - progress@2.0.3: {} + /progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: true - promise-inflight@1.0.1: {} + /promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + dev: true - promise-retry@2.0.1: + /promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} dependencies: err-code: 2.0.3 retry: 0.12.0 + dev: true - prompts-ncu@3.0.0: + /prompts-ncu@3.0.0: + resolution: {integrity: sha512-qyz9UxZ5MlPKWVhWrCmSZ1ahm2GVYdjLb8og2sg0IPth1KRuhcggHGuijz0e41dkx35p1t1q3GRISGH7QGALFA==} + engines: {node: '>= 14'} dependencies: kleur: 4.1.5 sisteransi: 1.0.5 + dev: true - proto-list@1.2.4: {} + /proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + dev: true - punycode@2.3.1: {} + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true - pupa@3.1.0: + /pupa@3.1.0: + resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} + engines: {node: '>=12.20'} dependencies: escape-goat: 4.0.0 + dev: true - queue-microtask@1.2.3: {} + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true - quick-lru@5.1.1: {} + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true - rc-config-loader@4.1.3: + /rc-config-loader@4.1.3: + resolution: {integrity: sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==} dependencies: debug: 4.3.4 js-yaml: 4.1.0 @@ -2733,103 +2079,186 @@ snapshots: require-from-string: 2.0.2 transitivePeerDependencies: - supports-color + dev: true - rc@1.2.8: + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true dependencies: deep-extend: 0.6.0 ini: 1.3.8 minimist: 1.2.8 strip-json-comments: 2.0.1 + dev: true - read-package-json-fast@3.0.2: + /read-package-json-fast@3.0.2: + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: json-parse-even-better-errors: 3.0.2 npm-normalize-package-bin: 3.0.1 + dev: true - read-package-json@6.0.4: + /read-package-json@6.0.4: + resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - glob: 10.3.12 + glob: 10.3.14 json-parse-even-better-errors: 3.0.2 normalize-package-data: 5.0.0 npm-normalize-package-bin: 3.0.1 + dev: true - readable-stream@3.6.2: + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 + dev: true - registry-auth-token@5.0.2: + /registry-auth-token@5.0.2: + resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} + engines: {node: '>=14'} dependencies: '@pnpm/npm-conf': 2.2.2 + dev: true - registry-url@6.0.1: + /registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} dependencies: rc: 1.2.8 + dev: true - remote-git-tags@3.0.0: {} + /remote-git-tags@3.0.0: + resolution: {integrity: sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==} + engines: {node: '>=8'} + dev: true - require-from-string@2.0.2: {} + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true - resolve-alpn@1.2.1: {} + /resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + dev: true - resolve-from@4.0.0: {} + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true - responselike@3.0.0: + /responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} dependencies: lowercase-keys: 3.0.0 + dev: true - restore-cursor@4.0.0: + /restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: onetime: 5.1.2 signal-exit: 3.0.7 + dev: true - retry@0.12.0: {} + /retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + dev: true - reusify@1.0.4: {} + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true - rfdc@1.3.1: {} + /rfdc@1.3.1: + resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} + dev: true - rimraf@3.0.2: + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true dependencies: glob: 7.2.3 + dev: true - rimraf@5.0.5: + /rimraf@5.0.6: + resolution: {integrity: sha512-X72SgyOf+1lFnGM6gYcmZ4+jMOwuT4E4SajKQzUIlI7EoR5eFHMhS/wf8Ll0mN+w2bxcIVldrJQ6xT7HFQywjg==} + engines: {node: '>=14'} + hasBin: true dependencies: - glob: 10.3.12 + glob: 10.3.14 + dev: true - run-parallel@1.2.0: + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 + dev: true - safe-buffer@5.2.1: {} + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true - safer-buffer@2.1.2: + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + requiresBuild: true + dev: true optional: true - semver-diff@4.0.0: + /semver-diff@4.0.0: + resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} + engines: {node: '>=12'} dependencies: semver: 7.6.0 + dev: true - semver-utils@1.1.4: {} + /semver-utils@1.1.4: + resolution: {integrity: sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==} + dev: true - semver@7.6.0: + /semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true dependencies: lru-cache: 6.0.0 + dev: true - set-blocking@2.0.0: {} + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true - shebang-command@2.0.0: + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 + dev: true - shebang-regex@3.0.0: {} + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true - signal-exit@3.0.7: {} + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true - signal-exit@4.1.0: {} + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true - sigstore@1.9.0: + /sigstore@1.9.0: + resolution: {integrity: sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true dependencies: '@sigstore/bundle': 1.1.0 '@sigstore/protobuf-specs': 0.2.1 @@ -2838,50 +2267,81 @@ snapshots: make-fetch-happen: 11.1.1 transitivePeerDependencies: - supports-color + dev: true - sisteransi@1.0.5: {} + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true - slash@3.0.0: {} + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true - slice-ansi@4.0.0: + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} dependencies: ansi-styles: 4.3.0 astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 + dev: true - slice-ansi@5.0.0: + /slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 4.0.0 + dev: true - slice-ansi@7.1.0: + /slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 + dev: true - smart-buffer@4.2.0: {} + /smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: true - socks-proxy-agent@7.0.0: + /socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} dependencies: agent-base: 6.0.2 debug: 4.3.4 socks: 2.8.3 transitivePeerDependencies: - supports-color + dev: true - socks@2.8.3: + /socks@2.8.3: + resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} dependencies: ip-address: 9.0.5 smart-buffer: 4.2.0 + dev: true - solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5): + /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5): + resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-solidity: ^1.0.0 dependencies: '@prettier/sync': 0.3.0(prettier@3.2.5) prettier: 3.2.5 prettier-linter-helpers: 1.0.0 prettier-plugin-solidity: 1.3.1(prettier@3.2.5) + dev: true - solhint@4.5.4: + /solhint@4.5.4: + resolution: {integrity: sha512-Cu1XiJXub2q1eCr9kkJ9VPv1sGcmj3V7Zb76B0CoezDOB9bu3DxKIFFH7ggCl9fWpEPD6xBmRLfZrYijkVmujQ==} + hasBin: true dependencies: '@solidity-parser/parser': 0.18.0 ajv: 6.12.6 @@ -2905,99 +2365,166 @@ snapshots: prettier: 2.8.8 transitivePeerDependencies: - typescript + dev: true - solidity-comments-extractor@0.0.8: {} + /solidity-comments-extractor@0.0.8: + resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} + dev: true - source-map-support@0.5.21: + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + dev: true - source-map@0.6.1: {} + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true - spawn-please@2.0.2: + /spawn-please@2.0.2: + resolution: {integrity: sha512-KM8coezO6ISQ89c1BzyWNtcn2V2kAVtwIXd3cN/V5a0xPYc1F/vydrRc01wsKFEQ/p+V1a4sw4z2yMITIXrgGw==} + engines: {node: '>=14'} dependencies: cross-spawn: 7.0.3 + dev: true - spdx-correct@3.2.0: + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.17 + dev: true - spdx-exceptions@2.5.0: {} + /spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + dev: true - spdx-expression-parse@3.0.1: + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} dependencies: spdx-exceptions: 2.5.0 spdx-license-ids: 3.0.17 + dev: true - spdx-license-ids@3.0.17: {} + /spdx-license-ids@3.0.17: + resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + dev: true - sprintf-js@1.1.3: {} + /sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + dev: true - ssri@10.0.6: + /ssri@10.0.6: + resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: - minipass: 7.1.0 + minipass: 7.1.1 + dev: true - ssri@9.0.1: + /ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: minipass: 3.3.6 + dev: true - string-argv@0.3.2: {} + /string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + dev: true - string-width@4.2.3: + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + dev: true - string-width@5.1.2: + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 + dev: true - string-width@7.1.0: + /string-width@7.1.0: + resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} + engines: {node: '>=18'} dependencies: emoji-regex: 10.3.0 get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 + dev: true - string_decoder@1.3.0: + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: safe-buffer: 5.2.1 + dev: true - strip-ansi@6.0.1: + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 + dev: true - strip-ansi@7.1.0: + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 + dev: true - strip-final-newline@3.0.0: {} + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true - strip-json-comments@2.0.1: {} + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: true - strip-json-comments@5.0.1: {} + /strip-json-comments@5.0.1: + resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} + engines: {node: '>=14.16'} + dev: true - supports-color@5.5.0: + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} dependencies: has-flag: 3.0.0 + dev: true - supports-color@7.2.0: + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} dependencies: has-flag: 4.0.0 + dev: true - table@6.8.1: + /table@6.8.1: + resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} + engines: {node: '>=10.0.0'} dependencies: ajv: 8.12.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 + dev: true - tar@6.2.1: + /tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} dependencies: chownr: 2.0.0 fs-minipass: 2.1.0 @@ -3005,54 +2532,94 @@ snapshots: minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 + dev: true - text-table@0.2.0: {} + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true - to-regex-range@5.0.1: + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 + dev: true - tuf-js@1.1.7: + /tuf-js@1.1.7: + resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: '@tufjs/models': 1.0.4 debug: 4.3.4 make-fetch-happen: 11.1.1 transitivePeerDependencies: - supports-color + dev: true - type-fest@1.4.0: {} + /type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: true - type-fest@2.19.0: {} + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: true - type-fest@3.13.1: {} + /type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + dev: true - typedarray-to-buffer@3.1.5: + /typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} dependencies: is-typedarray: 1.0.0 + dev: true - unique-filename@2.0.1: + /unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: unique-slug: 3.0.0 + dev: true - unique-filename@3.0.0: + /unique-filename@3.0.0: + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: unique-slug: 4.0.0 + dev: true - unique-slug@3.0.0: + /unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dependencies: imurmurhash: 0.1.4 + dev: true - unique-slug@4.0.0: + /unique-slug@4.0.0: + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dependencies: imurmurhash: 0.1.4 + dev: true - unique-string@3.0.0: + /unique-string@3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} dependencies: crypto-random-string: 4.0.0 + dev: true - untildify@4.0.0: {} + /untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + dev: true - update-notifier@6.0.2: + /update-notifier@6.0.2: + resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} + engines: {node: '>=14.16'} dependencies: boxen: 7.1.1 chalk: 5.3.0 @@ -3068,67 +2635,114 @@ snapshots: semver: 7.6.0 semver-diff: 4.0.0 xdg-basedir: 5.1.0 + dev: true - uri-js@4.4.1: + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.3.1 + dev: true - util-deprecate@1.0.2: {} + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true - validate-npm-package-license@3.0.4: + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + dev: true - validate-npm-package-name@5.0.1: {} + /validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true - which@2.0.2: + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true dependencies: isexe: 2.0.0 + dev: true - which@3.0.1: + /which@3.0.1: + resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true dependencies: isexe: 2.0.0 + dev: true - wide-align@1.1.5: + /wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} dependencies: string-width: 4.2.3 + dev: true - widest-line@4.0.1: + /widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} dependencies: string-width: 5.1.2 + dev: true - wrap-ansi@7.0.0: + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 + dev: true - wrap-ansi@8.1.0: + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 + dev: true - wrap-ansi@9.0.0: + /wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} dependencies: ansi-styles: 6.2.1 string-width: 7.1.0 strip-ansi: 7.1.0 + dev: true - wrappy@1.0.2: {} + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true - write-file-atomic@3.0.3: + /write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} dependencies: imurmurhash: 0.1.4 is-typedarray: 1.0.0 signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 + dev: true - xdg-basedir@5.1.0: {} + /xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + dev: true - yallist@4.0.0: {} + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true - yaml@2.3.4: {} + /yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + dev: true - yocto-queue@0.1.0: {} + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/src/EchoState.sol b/src/EchoState.sol index 121c393..987e901 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -1,9 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/EchoError.sol"; -import "contracts/types/Offer.sol"; -import "contracts/types/OfferItem.sol"; +import "./types/Offer.sol"; +import "./EchoError.sol"; abstract contract EchoState { mapping(bytes32 => Offer) public offers; diff --git a/src/wormhole/Message.sol b/src/wormhole/Message.sol index 27594dc..65ed06e 100644 --- a/src/wormhole/Message.sol +++ b/src/wormhole/Message.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/wormhole/BytesLib.sol"; -import "contracts/wormhole/WormholeError.sol"; +import "../../lib/wormhole/BytesLib.sol"; abstract contract Message { using BytesLib for bytes; diff --git a/src/wormhole/WormholeGovernance.sol b/src/wormhole/WormholeGovernance.sol index 8e8f602..92fc52f 100644 --- a/src/wormhole/WormholeGovernance.sol +++ b/src/wormhole/WormholeGovernance.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/wormhole/IWormhole.sol"; -import "contracts/wormhole/Message.sol"; -import "contracts/wormhole/WormholeError.sol"; -import "contracts/wormhole/WormholeState.sol"; import "solmate/auth/Owned.sol"; +import "./Message.sol"; +import "./WormholeError.sol"; +import "./WormholeState.sol"; +import "../../lib/wormhole/IWormhole.sol"; abstract contract WormholeGovernance is Owned, Message, WormholeState { constructor(address wormhole_, uint16 _chainId, uint8 wormholeFinality_) { diff --git a/src/wormhole/WormholeState.sol b/src/wormhole/WormholeState.sol index fbecf44..777769c 100644 --- a/src/wormhole/WormholeState.sol +++ b/src/wormhole/WormholeState.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "contracts/wormhole/IWormhole.sol"; -import "contracts/wormhole/WormholeError.sol"; import "solmate/auth/Owned.sol"; +import "./WormholeError.sol"; +import "../../lib/wormhole/IWormhole.sol"; struct State { // address of the Wormhole contract on this chain diff --git a/test/Admin.t.sol b/test/Admin.t.sol index d072e61..6cc67b8 100644 --- a/test/Admin.t.sol +++ b/test/Admin.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract AdminTest is BaseTest { @@ -24,73 +23,4 @@ contract AdminTest is BaseTest { echo.setPaused(false); assertEq(echo.paused(), false); } - - function testCannotWithdrawIfNotOwner() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - _executeMockTrade("test", account1, account2, 0.005 ether); - - vm.prank(account1); - vm.expectRevert("UNAUTHORIZED"); - echo.withdraw(account1); - } - - function testCanWithdrawToSelfIfOwner() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - _executeMockTrade("test", account1, account2, 0.005 ether); - - assertEq(address(echo).balance, 0.005 ether); - vm.prank(owner); - echo.withdraw(owner); - assertEq(owner.balance, 0.005 ether); - assertEq(address(echo).balance, 0); - } - - function testCanWithdrawToOtherAccountIfOwner() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - _executeMockTrade("test", account1, account2, 0.005 ether); - - vm.prank(owner); - echo.withdraw(account3); - assertEq(account3.balance, 100 ether + 0.005 ether); - assertEq(address(echo).balance, 0); - } - - function testCannotWithdrawToContractIfOwner() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - _executeMockTrade("test", account1, account2, 0.005 ether); - - vm.prank(owner); - vm.expectRevert(WithdrawFailed.selector); - echo.withdraw(address(echo)); - assertEq(account3.balance, 100 ether); - assertEq(address(echo).balance, 0.005 ether); - } } diff --git a/test/Banker.t.sol b/test/Banker.t.sol index a97007e..a17e1fb 100644 --- a/test/Banker.t.sol +++ b/test/Banker.t.sol @@ -17,73 +17,73 @@ contract BankerTest is BaseTest { echo.setFees(0.005 ether); assertEq(echo.tradingFee(), 0.005 ether); } - - function testCannotWithdrawIfNotOwner() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - _executeMockTrade("test", account1, account2, 0.005 ether); - - vm.prank(account1); - vm.expectRevert("UNAUTHORIZED"); - echo.withdraw(account1); - } - - function testCanWithdrawToSelfIfOwner() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - _executeMockTrade("test", account1, account2, 0.005 ether); - - assertEq(address(echo).balance, 0.005 ether); - vm.prank(owner); - echo.withdraw(owner); - assertEq(owner.balance, 0.005 ether); - assertEq(address(echo).balance, 0); - } - - function testCanWithdrawToOtherAccountIfOwner() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - _executeMockTrade("test", account1, account2, 0.005 ether); - - vm.prank(owner); - echo.withdraw(account3); - assertEq(account3.balance, 100 ether + 0.005 ether); - assertEq(address(echo).balance, 0); - } - - function testCannotWithdrawToContractIfOwner() public { - // Set fees - vm.prank(owner); - echo.setFees(0.005 ether); - - creator721Collections.push(apeAddress); - creator721Ids.push(ape1Id); - counterparty721Collections.push(birdAddress); - counterparty721Ids.push(bird1Id); - _executeMockTrade("test", account1, account2, 0.005 ether); - - vm.prank(owner); - vm.expectRevert(WithdrawFailed.selector); - echo.withdraw(address(echo)); - assertEq(account3.balance, 100 ether); - assertEq(address(echo).balance, 0.005 ether); - } + // TODO Fix this once we have utils functions to execute a swap + // function testCannotWithdrawIfNotOwner() public { + // // Set fees + // vm.prank(owner); + // echo.setFees(0.005 ether); + // + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // _executeMockTrade("test", account1, account2, 0.005 ether); + // + // vm.prank(account1); + // vm.expectRevert("UNAUTHORIZED"); + // echo.withdraw(account1); + // } + // + // function testCanWithdrawToSelfIfOwner() public { + // // Set fees + // vm.prank(owner); + // echo.setFees(0.005 ether); + // + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // _executeMockTrade("test", account1, account2, 0.005 ether); + // + // assertEq(address(echo).balance, 0.005 ether); + // vm.prank(owner); + // echo.withdraw(owner); + // assertEq(owner.balance, 0.005 ether); + // assertEq(address(echo).balance, 0); + // } + // + // function testCanWithdrawToOtherAccountIfOwner() public { + // // Set fees + // vm.prank(owner); + // echo.setFees(0.005 ether); + // + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // _executeMockTrade("test", account1, account2, 0.005 ether); + // + // vm.prank(owner); + // echo.withdraw(account3); + // assertEq(account3.balance, 100 ether + 0.005 ether); + // assertEq(address(echo).balance, 0); + // } + // + // function testCannotWithdrawToContractIfOwner() public { + // // Set fees + // vm.prank(owner); + // echo.setFees(0.005 ether); + // + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // _executeMockTrade("test", account1, account2, 0.005 ether); + // + // vm.prank(owner); + // vm.expectRevert(WithdrawFailed.selector); + // echo.withdraw(address(echo)); + // assertEq(account3.balance, 100 ether); + // assertEq(address(echo).balance, 0.005 ether); + // } } diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index e2b9b8f..330b98c 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -3,14 +3,13 @@ pragma solidity ^0.8.18; import "./mock/Mocked721.sol"; import "./mock/MockHandler.sol"; -import "./mock/WormholeSimulator.sol"; import "forge-std/Test.sol"; import "./utils/OfferUtils.sol"; import "../src/EchoCrossChain.sol"; abstract contract BaseTest is Test, OfferUtils { // Exclude from coverage report - function test() public {} + function test() public override {} EchoCrossChain public echo; diff --git a/test/CreateOffer.t.sol b/test/CreateOffer.t.sol index 772b181..cbc9526 100644 --- a/test/CreateOffer.t.sol +++ b/test/CreateOffer.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; -import "./BaseTest.t.sol"; import "forge-std/Test.sol"; +import "./BaseTest.t.sol"; import "../src/types/OfferItems.sol"; import "../src/types/Offer.sol"; @@ -26,7 +26,7 @@ contract CreateOfferTest is BaseTest { receiverTokenIds, block.chainid, in6hours, - OfferState.ACCEPTED + OfferState.OPEN ); vm.prank(account1); @@ -53,7 +53,7 @@ contract CreateOfferTest is BaseTest { receiverTokenIds, block.chainid, in6hours, - OfferState.ACCEPTED + OfferState.OPEN ); vm.prank(account1); @@ -118,37 +118,38 @@ contract CreateOfferTest is BaseTest { vm.expectRevert(InvalidSender.selector); echo.createOffer(offer); } - - function testCannotCreateDuplicateOffer() public { - Offer memory firstOffer = _createMockOffer(); - - address[] memory senderTokenAddresses = new address[](1); - senderTokenAddresses[0] = apeAddress; - uint256[] memory senderTokenIds = new uint256[](1); - senderTokenIds[0] = ape1Id; - - address[] memory receiverTokenAddresses = new address[](1); - receiverTokenAddresses[0] = birdAddress; - uint256[] memory receiverTokenIds = new uint256[](1); - receiverTokenIds[0] = bird1Id; - - Offer memory secondOffer = generateOffer( - account1, - senderTokenAddresses, - senderTokenIds, - block.chainid, - account2, - receiverTokenAddresses, - receiverTokenIds, - block.chainid, - in6hours, - OfferState.OPEN - ); - - vm.prank(account1); - vm.expectRevert(OfferAlreadyExist.selector); - echo.createOffer(secondOffer); - } + // TODO Not sure if this case if even possible since the assets are deposited on an offer creation + // so it's impossible to recreate the same offer ID + // function testCannotCreateDuplicateOffer() public { + // Offer memory firstOffer = _createMockOffer(); + // + // address[] memory senderTokenAddresses = new address[](1); + // senderTokenAddresses[0] = apeAddress; + // uint256[] memory senderTokenIds = new uint256[](1); + // senderTokenIds[0] = ape1Id; + // + // address[] memory receiverTokenAddresses = new address[](1); + // receiverTokenAddresses[0] = birdAddress; + // uint256[] memory receiverTokenIds = new uint256[](1); + // receiverTokenIds[0] = bird1Id; + // + // Offer memory secondOffer = generateOffer( + // account1, + // senderTokenAddresses, + // senderTokenIds, + // block.chainid, + // account2, + // receiverTokenAddresses, + // receiverTokenIds, + // block.chainid, + // in6hours, + // OfferState.OPEN + // ); + // + // vm.prank(account1); + // vm.expectRevert(OfferAlreadyExist.selector); + // echo.createOffer(secondOffer); + // } // Creating a same chain offer function testCanCreateOfferSingleAsset() public { diff --git a/test/mock/MockHandler.sol b/test/mock/MockHandler.sol index 0a7c2e1..94485cc 100644 --- a/test/mock/MockHandler.sol +++ b/test/mock/MockHandler.sol @@ -1,6 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; -import "contracts/escrow/EscrowHandler.sol"; +import "../../src/escrow/EscrowHandler.sol"; -contract MockedHandler is EscrowHandler {} +contract MockedHandler is EscrowHandler { + // Exclude from coverage report + function test() public {} +} diff --git a/test/mock/MockWormhole.sol b/test/mock/MockWormhole.sol index a160349..5829702 100644 --- a/test/mock/MockWormhole.sol +++ b/test/mock/MockWormhole.sol @@ -1,10 +1,13 @@ // SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.18; -import "contracts/wormhole/IWormhole.sol"; -import "contracts/wormhole/BytesLib.sol"; +import "../../lib/wormhole/BytesLib.sol"; +import "../../lib/wormhole/IWormhole.sol"; contract MockWormhole is IWormhole { + // Exclude from coverage report + function test() public {} + using BytesLib for bytes; uint256 private constant VM_VERSION_SIZE = 1; diff --git a/test/mock/WormholeSimulator.sol b/test/mock/WormholeSimulator.sol index 00227a6..7b79404 100644 --- a/test/mock/WormholeSimulator.sol +++ b/test/mock/WormholeSimulator.sol @@ -2,16 +2,16 @@ pragma solidity ^0.8.18; import "./MockWormhole.sol"; -import "contracts/wormhole/BytesLib.sol"; -import "contracts/wormhole/IWormhole.sol"; import "forge-std/Vm.sol"; -import "forge-std/console.sol"; /** * @notice These are the common parts for the signing and the non signing wormhole simulators. * @dev This contract is meant to be used when testing against a mainnet fork. */ abstract contract WormholeSimulator { + // Exclude from coverage report + function test() public virtual {} + using BytesLib for bytes; function doubleKeccak256(bytes memory body) internal pure returns (bytes32) { @@ -159,6 +159,9 @@ abstract contract WormholeSimulator { * as its hash wasn't banned. */ contract FakeWormholeSimulator is WormholeSimulator { + // Exclude from coverage report + function test() public override {} + // Allow access to Wormhole MockWormhole public wormhole; @@ -281,6 +284,9 @@ contract FakeWormholeSimulator is WormholeSimulator { * @dev This contract is meant to be used when testing against a mainnet fork. */ contract SigningWormholeSimulator is WormholeSimulator { + // Exclude from coverage report + function test() public override {} + // Taken from forge-std/Script.sol address private constant VM_ADDRESS = address(bytes20(uint160(uint256(keccak256("hevm cheat code"))))); Vm public constant vm = Vm(VM_ADDRESS); diff --git a/test/utils/OfferUtils.sol b/test/utils/OfferUtils.sol index 771f7d7..52415b6 100644 --- a/test/utils/OfferUtils.sol +++ b/test/utils/OfferUtils.sol @@ -8,6 +8,9 @@ import "../../src/types/OfferItem.sol"; import "../../src/types/OfferItems.sol"; abstract contract OfferUtils is Test { + // Exclude from coverage report + function test() public virtual {} + OfferItem[] public senderItems; OfferItem[] public receiverItems; @@ -40,9 +43,9 @@ abstract contract OfferUtils is Test { uint256 expiration, OfferState state ) public returns (Offer memory offer) { - require(senderTokenAddresses.length != senderTokenIds.length, "Sender items arrays do not match"); + require(senderTokenAddresses.length == senderTokenIds.length, "Sender items arrays do not match"); - require(receiverTokenAddresses.length != receiverTokenIds.length, "Receiver items arrays do not match"); + require(receiverTokenAddresses.length == receiverTokenIds.length, "Receiver items arrays do not match"); for (uint256 i = 0; i < senderTokenAddresses.length; i++) { senderItems.push(OfferItem({tokenAddress: senderTokenAddresses[i], tokenId: senderTokenIds[i]})); From 54eb97c901cb1eb4e2e20897db18dc006aec38be Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Fri, 10 May 2024 17:59:35 -0400 Subject: [PATCH 13/28] finished testing create offer --- src/EchoState.sol | 57 --------------------------- test/CreateOffer.t.sol | 88 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 57 deletions(-) diff --git a/src/EchoState.sol b/src/EchoState.sol index 987e901..35aaaed 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -84,63 +84,6 @@ abstract contract EchoState { delete offers[offerId]; } - // @dev Internal function to create a cross chain offer. We don't do a check on the addresses here - // because it might be triggered from a cross chain call. The check is done in the main Echo contract - function _createCrossChainOffer(Offer calldata offer, uint16 chainId) internal { - bytes32 offerId = _generateOfferId(offer); - - _validateOffer(offerId, offer); - - // @dev Chain must be the same as contract for sender items on cross chain offers - if (offer.senderItems.chainId != chainId) { - revert InvalidAssets(); - } - - // @dev Cannot create a cross chain offer on the same chain - if (offer.receiverItems.chainId == chainId) { - revert InvalidAssets(); - } - - offers[offerId] = offer; - } - - // @dev Internal function to accept the offer. We don't do a check on the addresses here - // because it might be triggered from a cross chain call. The check is done in the main Echo contract - function _acceptCrossChainOffer(bytes32 offerId) internal { - if (offers[offerId].sender == address(0)) { - revert OfferDoesNotExist(); - } - Offer memory offer = offers[offerId]; - - if (offer.expiration <= block.timestamp) { - revert OfferHasExpired(); - } - - // @dev Cannot accept an offer if it's not OPEN - if (offer.state != OfferState.OPEN) { - revert InvalidOfferState(); - } - // TODO Try if we can just change the variable - offers[offerId].state = OfferState.ACCEPTED; - } - - function _executeCrossChainOffer(bytes32 offerId) internal { - if (offers[offerId].sender == address(0)) { - revert OfferDoesNotExist(); - } - Offer memory offer = offers[offerId]; - - if (offer.expiration <= block.timestamp) { - revert OfferHasExpired(); - } - // @dev Cannot execute an offer if it's not ACCEPTED - if (offer.state != OfferState.ACCEPTED) { - revert InvalidOfferState(); - } - - delete offers[offerId]; - } - modifier offerNotExpired(uint256 expiration) { if (expiration <= block.timestamp) { revert OfferHasExpired(); diff --git a/test/CreateOffer.t.sol b/test/CreateOffer.t.sol index cbc9526..a84d248 100644 --- a/test/CreateOffer.t.sol +++ b/test/CreateOffer.t.sol @@ -7,6 +7,35 @@ import "../src/types/OfferItems.sol"; import "../src/types/Offer.sol"; contract CreateOfferTest is BaseTest { + function testCannotCreateOfferIfAlreadyExpired() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + block.timestamp, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(OfferHasExpired.selector); + echo.createOffer(offer); + } + function testCannotCreateOfferIfReceiverItemsIsEmpty() public { address[] memory senderTokenAddresses = new address[](1); senderTokenAddresses[0] = apeAddress; @@ -182,4 +211,63 @@ contract CreateOfferTest is BaseTest { // validate that the receiver items are not in escrow assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); } + + function testCanCreateOfferMultipleAssets() public { + address[] memory senderTokenAddresses = new address[](2); + senderTokenAddresses[0] = apeAddress; + senderTokenAddresses[1] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](2); + senderTokenIds[0] = ape1Id; + senderTokenIds[1] = ape2Id; + + address[] memory receiverTokenAddresses = new address[](2); + receiverTokenAddresses[0] = birdAddress; + receiverTokenAddresses[1] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](2); + receiverTokenIds[0] = bird1Id; + receiverTokenIds[1] = bird2Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + echo.createOffer(offer); + + // validate the offer id + bytes32 offerId = generateOfferId(offer); + ( + address sender, + address receiver, + OfferItems memory senderItems, + OfferItems memory receiverItems, + uint256 expiration, + OfferState state + ) = echo.offers(offerId); + assertOfferEq( + offer, + Offer({ + sender: sender, + receiver: receiver, + senderItems: senderItems, + receiverItems: receiverItems, + expiration: expiration, + state: state + }) + ); + + // validate that the sender items are in escrow + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + // validate that the receiver items are not in escrow + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + } } From ebacc3efb35543520fa1929b2528b362257bce19 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Fri, 10 May 2024 18:50:16 -0400 Subject: [PATCH 14/28] Tested accept offer --- src/EchoState.sol | 1 - test/AcceptOffer.t.sol | 193 +++++++++++++++++++++++++++++++++++++++++ test/BaseTest.t.sol | 10 +++ test/CreateOffer.t.sol | 32 ++++++- 4 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 test/AcceptOffer.t.sol diff --git a/src/EchoState.sol b/src/EchoState.sol index 35aaaed..fd78813 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -71,7 +71,6 @@ abstract contract EchoState { if (offer.state != OfferState.OPEN) { revert InvalidOfferState(); } - // TODO Try if we can just change the variable offers[offerId].state = OfferState.ACCEPTED; } diff --git a/test/AcceptOffer.t.sol b/test/AcceptOffer.t.sol new file mode 100644 index 0000000..51e881d --- /dev/null +++ b/test/AcceptOffer.t.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; +import "./BaseTest.t.sol"; +import "../src/types/OfferItems.sol"; +import "../src/types/Offer.sol"; + +contract AcceptOfferTest is BaseTest { + function testCannotAcceptOfferIfPaused() public { + Offer memory offer = _createMockOffer(); + bytes32 offerId = generateOfferId(offer); + _setPaused(); + + vm.prank(account2); + vm.expectRevert(Paused.selector); + echo.acceptOffer(offerId); + } + + function testCannotAcceptOfferIfAlreadyExpired() public { + Offer memory offer = _createMockOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.warp(in6hours); + vm.prank(account2); + vm.expectRevert(OfferHasExpired.selector); + echo.acceptOffer(offerId); + } + + function testCannotAcceptNonExistentOffer() public { + _createMockOffer(); + + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape2Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird2Id; + + Offer memory invalidOffer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + bytes32 offerId = generateOfferId(invalidOffer); + + vm.prank(account2); + vm.expectRevert(OfferDoesNotExist.selector); + echo.acceptOffer(offerId); + } + + function testCannotAcceptOfferIfNotEnoughFunds() public { + _setFees(); + Offer memory offer = _createMockOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + vm.expectRevert(InvalidPayment.selector); + echo.acceptOffer(offerId); + } + + function testCannotAcceptOfferIfNotReceiver() public { + Offer memory offer = _createMockOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account3); + vm.expectRevert(InvalidReceiver.selector); + echo.acceptOffer(offerId); + } + + function testCanAcceptOfferSingleAsset() public { + Offer memory offer = _createMockOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + echo.acceptOffer(offerId); + + Offer memory updatedOffer = Offer({ + sender: offer.sender, + receiver: offer.receiver, + senderItems: offer.senderItems, + receiverItems: offer.receiverItems, + expiration: offer.expiration, + state: OfferState.ACCEPTED + }); + + ( + address sender, + address receiver, + OfferItems memory senderItems, + OfferItems memory receiverItems, + uint256 expiration, + OfferState state + ) = echo.offers(offerId); + assertOfferEq( + updatedOffer, + Offer({ + sender: sender, + receiver: receiver, + senderItems: senderItems, + receiverItems: receiverItems, + expiration: expiration, + state: state + }) + ); + + // validate that the sender items are in escrow + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + // validate that the receiver items are in escrow + assertOfferItemsOwnership(offer.receiverItems.items, address(echo)); + } + + function testCanAcceptOfferMultipleAssets() public { + address[] memory senderTokenAddresses = new address[](2); + senderTokenAddresses[0] = apeAddress; + senderTokenAddresses[1] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](2); + senderTokenIds[0] = ape1Id; + senderTokenIds[1] = ape2Id; + + address[] memory receiverTokenAddresses = new address[](2); + receiverTokenAddresses[0] = birdAddress; + receiverTokenAddresses[1] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](2); + receiverTokenIds[0] = bird1Id; + receiverTokenIds[1] = bird2Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + echo.createOffer(offer); + + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + echo.acceptOffer(offerId); + + Offer memory updatedOffer = Offer({ + sender: offer.sender, + receiver: offer.receiver, + senderItems: offer.senderItems, + receiverItems: offer.receiverItems, + expiration: offer.expiration, + state: OfferState.ACCEPTED + }); + + ( + address sender, + address receiver, + OfferItems memory senderItems, + OfferItems memory receiverItems, + uint256 expiration, + OfferState state + ) = echo.offers(offerId); + assertOfferEq( + updatedOffer, + Offer({ + sender: sender, + receiver: receiver, + senderItems: senderItems, + receiverItems: receiverItems, + expiration: expiration, + state: state + }) + ); + + // validate that the sender items are in escrow + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + // validate that the receiver items are in escrow + assertOfferItemsOwnership(offer.receiverItems.items, address(echo)); + } +} diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index 330b98c..6dfc0cd 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -117,6 +117,16 @@ abstract contract BaseTest is Test, OfferUtils { echo.createOffer(offer); } + function _setFees() internal { + vm.prank(owner); + echo.setFees(0.005 ether); + } + + function _setPaused() internal { + vm.prank(owner); + echo.setPaused(true); + } + // @dev Method to execute a mock trade with predefined values // @dev Do not use this method if you expect a revert as the way Foundry is built, it won't catch the revert function _executeMockTrade(string memory id, address creator, address counter, uint256 fees) internal { diff --git a/test/CreateOffer.t.sol b/test/CreateOffer.t.sol index a84d248..23bd4f5 100644 --- a/test/CreateOffer.t.sol +++ b/test/CreateOffer.t.sol @@ -7,6 +7,37 @@ import "../src/types/OfferItems.sol"; import "../src/types/Offer.sol"; contract CreateOfferTest is BaseTest { + function testCannotCreateOfferIfPaused() public { + _setPaused(); + + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(Paused.selector); + echo.createOffer(offer); + } + function testCannotCreateOfferIfAlreadyExpired() public { address[] memory senderTokenAddresses = new address[](1); senderTokenAddresses[0] = apeAddress; @@ -179,7 +210,6 @@ contract CreateOfferTest is BaseTest { // vm.expectRevert(OfferAlreadyExist.selector); // echo.createOffer(secondOffer); // } - // Creating a same chain offer function testCanCreateOfferSingleAsset() public { Offer memory offer = _createMockOffer(); From 3541e86b6b21188c64e61378bf4966935b901736 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Fri, 10 May 2024 20:46:36 -0400 Subject: [PATCH 15/28] Testing almost done Started working on redeeming expired offers --- script/DeployEchoCrossChain.s.sol | 6 +- src/Echo.sol | 97 ++++++ src/EchoCrossChain.sol | 171 ---------- src/EchoError.sol | 2 + src/EchoState.sol | 8 + test/AcceptOffer.t.sol | 80 +---- test/Banker.t.sol | 110 +++---- test/BaseTest.t.sol | 109 ++++--- test/CancelOffer.t.sol | 75 +++++ test/CreateOffer.t.sol | 174 +--------- test/ExecuteOffer.t.sol | 84 +++++ test/Expiration.t.sol | 105 +++--- test/Fees.t.sol | 94 ++---- test/Handler.t.sol | 31 -- test/Ownership.t.sol | 144 +++------ test/Paused.t.sol | 69 ++++ test/TestBridge.t.sol | 169 ---------- test/WrongAssets.t.sol | 515 ++++++++++++++++-------------- test/mock/MockHandler.sol | 9 - 19 files changed, 868 insertions(+), 1184 deletions(-) create mode 100644 src/Echo.sol delete mode 100644 src/EchoCrossChain.sol create mode 100644 test/CancelOffer.t.sol create mode 100644 test/ExecuteOffer.t.sol delete mode 100644 test/Handler.t.sol create mode 100644 test/Paused.t.sol delete mode 100644 test/TestBridge.t.sol delete mode 100644 test/mock/MockHandler.sol diff --git a/script/DeployEchoCrossChain.s.sol b/script/DeployEchoCrossChain.s.sol index 6ddaca3..f13a394 100644 --- a/script/DeployEchoCrossChain.s.sol +++ b/script/DeployEchoCrossChain.s.sol @@ -2,15 +2,15 @@ pragma solidity ^0.8.18; import "forge-std/Script.sol"; -import "../src/EchoCrossChain.sol"; +import "../src/Echo.sol"; -contract DeployEchoCrossChain is Script { +contract DeployEcho is Script { // Exclude from coverage report function test() public {} function run() external { vm.startBroadcast(); - new EchoCrossChain({owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09)}); + new Echo({owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09)}); vm.stopBroadcast(); } diff --git a/src/Echo.sol b/src/Echo.sol new file mode 100644 index 0000000..25a9a7a --- /dev/null +++ b/src/Echo.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "solmate/utils/ReentrancyGuard.sol"; +import "./Admin.sol"; +import "./Banker.sol"; +import "./EchoError.sol"; +import "./EchoState.sol"; +import "./escrow/Escrow.sol"; +import "./types/Offer.sol"; + +contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { + // @dev For future use... + uint16 private chainId; + + constructor(address owner) Admin(owner) { + chainId = uint16(block.chainid); + } + + /** + * Same chain offers + */ + function createOffer(Offer calldata offer) external nonReentrant notPaused { + // @dev Cannot accept an offer if not the receiver + if (offer.sender != msg.sender) { + revert InvalidSender(); + } + _deposit(offer.senderItems, offer.sender); + _createOffer(offer, chainId); + } + + function acceptOffer(bytes32 offerId) external payable nonReentrant notPaused { + if (msg.value != tradingFee) { + revert InvalidPayment(); + } + Offer memory offer = offers[offerId]; + + // @dev We dont do a check on whether the offer exsits or not because + // if it doesn't exist offer.receiver = address(0) which can't be msg.sender + if (offer.receiver != msg.sender) { + revert InvalidReceiver(); + } + + _deposit(offer.receiverItems, offer.receiver); + _acceptOffer(offerId, offer); + } + + function cancelOffer(bytes32 offerId) external nonReentrant notPaused { + Offer memory offer = offers[offerId]; + + // @dev We dont do a check on whether the offer exsits or not because + // if it doesn't exist offer.sender = address(0) which can't be msg.sender + if (offer.sender != msg.sender) { + revert InvalidReceiver(); + } + + // @dev Refund sender + _withdraw(offer.senderItems, offer.sender); + _cancelOffer(offerId, offer); + } + + function executeOffer(bytes32 offerId) external payable nonReentrant notPaused { + if (msg.value != tradingFee) { + revert InvalidPayment(); + } + Offer memory offer = offers[offerId]; + + // @dev We dont do a check on whether the offer exsits or not because + // if it doesn't exist offer.sender = address(0) which can't be msg.sender + if (offer.sender != msg.sender) { + revert InvalidSender(); + } + _withdraw(offer.senderItems, offer.receiver); + _withdraw(offer.receiverItems, offer.sender); + _executeOffer(offerId, offer); + } + + // @dev Function to redeem NFTs if offer expired and trade was not executed + function redeemOffer(bytes32 offerId) external nonReentrant notPaused { + Offer memory offer = offers[offerId]; + + if (msg.sender != offer.sender && msg.sender != offer.receiver) { + revert InvalidRecipient(); + } + + if (offer.expiration > block.timestamp) { + revert OfferHasNotExpired(); + } + + // @dev We know sender is either sender or receiver here, no need to check both + if (msg.sender == offer.sender) { + _withdraw(offer.senderItems, offer.sender); + } else { + _withdraw(offer.receiverItems, offer.receiver); + } + } +} diff --git a/src/EchoCrossChain.sol b/src/EchoCrossChain.sol deleted file mode 100644 index 7d66aa2..0000000 --- a/src/EchoCrossChain.sol +++ /dev/null @@ -1,171 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "solmate/utils/ReentrancyGuard.sol"; -import "./Admin.sol"; -import "./Banker.sol"; -import "./EchoState.sol"; -import "./escrow/Escrow.sol"; -import "./types/Offer.sol"; - -contract EchoCrossChain is ReentrancyGuard, Admin, Banker, Escrow, EchoState { - // @dev For future use... - uint16 private chainId; - - constructor(address owner) Admin(owner) { - chainId = uint16(block.chainid); - } - - /** - * Same chain offers - */ - function createOffer(Offer calldata offer) external nonReentrant notPaused { - // @dev Cannot accept an offer if not the receiver - if (offer.sender != msg.sender) { - revert InvalidSender(); - } - _deposit(offer.senderItems, offer.sender); - _createOffer(offer, chainId); - } - - function acceptOffer(bytes32 offerId) external payable nonReentrant notPaused { - if (msg.value != tradingFee) { - revert InvalidPayment(); - } - Offer memory offer = offers[offerId]; - - if (offer.sender == address(0)) { - revert OfferDoesNotExist(); - } - if (offer.receiver != msg.sender) { - revert InvalidReceiver(); - } - - _deposit(offer.receiverItems, offer.receiver); - _acceptOffer(offerId, offer); - } - - function executeSwap(bytes32 offerId) external payable nonReentrant notPaused { - if (msg.value != tradingFee) { - revert InvalidPayment(); - } - Offer memory offer = offers[offerId]; - - if (offer.sender == address(0)) { - revert OfferDoesNotExist(); - } - - if (offer.sender != msg.sender) { - revert InvalidSender(); - } - _withdraw(offer.senderItems, offer.receiver); - _withdraw(offer.receiverItems, offer.sender); - _executeOffer(offerId, offer); - } - - /** - * Cross chain offers - */ - function createCrossChainOffer(Offer calldata offer) external payable nonReentrant notPaused { - // @dev Cannot accept an offer if not the receiver - if (offer.sender != msg.sender) { - revert InvalidSender(); - } - } - - // @dev This function assumes that the offer was created on another chain. - function acceptOffer( - string calldata offerId, - Offer calldata offer, - bytes memory encodedMessage - ) external payable nonReentrant notPaused { - // if (_offers[offerId].sender != address(0)) { - // revert OfferAlreadyExist(); - // } - // // @dev Cannot accept an offer if not the receiver - // if (offer.receiver != msg.sender) { - // revert InvalidCounterparty(); - // } - // - // if (offer.expiresAt <= block.timestamp) { - // revert OfferHasExpired(); - // } - // - // if (offer.status != OfferStatus.Created) { - // revert InvalidOfferStatus(); - // } - // - // // Validate that the offer was created on the other chain - // EchoMessage memory message = _receiveMessage(encodedMessage); - // _validateMessage(message, offer); - // - // _depositForReceiver(offer); - // _offers[offerId] = offer; - // - // // @dev FIXME the message should change - // EchoMessageWithoutPayload memory newMessage = EchoMessageWithoutPayload({ - // id: message.id, - // evmSender: message.evmSender, - // evmReceiver: message.evmReceiver, - // evmTokenAddress: message.evmTokenAddress, - // evmTokenId: message.evmTokenId, - // solSender: message.solSender, - // solReceiver: message.solReceiver, - // solSenderTokenMint: message.solSenderTokenMint - // }); - // _sendMessage(newMessage); - } - - function executeTrade() external payable nonReentrant notPaused { - // if (trades[trade.id]) { - // revert TradeAlreadyExist(); - // } - // - // if (trade.creator != msg.sender) { - // revert InvalidCreator(); - // } - // - // // We only check that length is not 0 here because we check the length in the transfer method - // if (trade.creatorCollections.length == 0 || trade.counterpartyCollections.length == 0) { - // revert InvalidAssets(); - // } - // - // if (trade.expiresAt <= block.timestamp) { - // revert TradeHasExpired(); - // } - // - // if (msg.value != tradingFee) { - // revert InvalidPayment(); - // } - // - // _validateSignature(v, r, s, signatureData, signer); - // _validateTrade(signatureData, trade); - // - // // Transfer creator's assets - // _transferTokens({ - // collections: trade.creatorCollections, - // ids: trade.creatorIds, - // from: trade.creator, - // to: trade.counterparty - // }); - // - // // Transfer counterparty's assets - // _transferTokens({ - // collections: trade.counterpartyCollections, - // ids: trade.counterpartyIds, - // from: trade.counterparty, - // to: trade.creator - // }); - // - // // Add trade to list to avoid replay and duplicates - // trades[trade.id] = true; - // emit TradeExecuted(trade.id); - } - - // // @dev Wormhole function to receive messages and update trades - // function receiveMessage( - // bytes memory encodedMessage - // ) public returns (EchoMessage memory parsedMessage) { - // parsedMessage = _receiveMessage(encodedMessage); - // } -} diff --git a/src/EchoError.sol b/src/EchoError.sol index 92332c7..a0a5d57 100644 --- a/src/EchoError.sol +++ b/src/EchoError.sol @@ -6,6 +6,8 @@ error InvalidOfferState(); error InvalidPayment(); error InvalidReceiver(); error InvalidSender(); +error InvalidRecipient(); error OfferAlreadyExist(); error OfferDoesNotExist(); error OfferHasExpired(); +error OfferHasNotExpired(); diff --git a/src/EchoState.sol b/src/EchoState.sol index fd78813..9469e47 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -74,6 +74,14 @@ abstract contract EchoState { offers[offerId].state = OfferState.ACCEPTED; } + function _cancelOffer(bytes32 offerId, Offer memory offer) internal offerNotExpired(offer.expiration) { + // @dev Cannot cancel an offer if it's not OPEN + if (offer.state != OfferState.OPEN) { + revert InvalidOfferState(); + } + delete offers[offerId]; + } + function _executeOffer(bytes32 offerId, Offer memory offer) internal offerNotExpired(offer.expiration) { // @dev Cannot execute an offer if it's not ACCEPTED if (offer.state != OfferState.ACCEPTED) { diff --git a/test/AcceptOffer.t.sol b/test/AcceptOffer.t.sol index 51e881d..5ea30b7 100644 --- a/test/AcceptOffer.t.sol +++ b/test/AcceptOffer.t.sol @@ -7,29 +7,7 @@ import "../src/types/OfferItems.sol"; import "../src/types/Offer.sol"; contract AcceptOfferTest is BaseTest { - function testCannotAcceptOfferIfPaused() public { - Offer memory offer = _createMockOffer(); - bytes32 offerId = generateOfferId(offer); - _setPaused(); - - vm.prank(account2); - vm.expectRevert(Paused.selector); - echo.acceptOffer(offerId); - } - - function testCannotAcceptOfferIfAlreadyExpired() public { - Offer memory offer = _createMockOffer(); - bytes32 offerId = generateOfferId(offer); - - vm.warp(in6hours); - vm.prank(account2); - vm.expectRevert(OfferHasExpired.selector); - echo.acceptOffer(offerId); - } - function testCannotAcceptNonExistentOffer() public { - _createMockOffer(); - address[] memory senderTokenAddresses = new address[](1); senderTokenAddresses[0] = apeAddress; uint256[] memory senderTokenIds = new uint256[](1); @@ -55,36 +33,14 @@ contract AcceptOfferTest is BaseTest { bytes32 offerId = generateOfferId(invalidOffer); vm.prank(account2); - vm.expectRevert(OfferDoesNotExist.selector); - echo.acceptOffer(offerId); - } - - function testCannotAcceptOfferIfNotEnoughFunds() public { - _setFees(); - Offer memory offer = _createMockOffer(); - bytes32 offerId = generateOfferId(offer); - - vm.prank(account2); - vm.expectRevert(InvalidPayment.selector); - echo.acceptOffer(offerId); - } - - function testCannotAcceptOfferIfNotReceiver() public { - Offer memory offer = _createMockOffer(); - bytes32 offerId = generateOfferId(offer); - - vm.prank(account3); vm.expectRevert(InvalidReceiver.selector); echo.acceptOffer(offerId); } function testCanAcceptOfferSingleAsset() public { - Offer memory offer = _createMockOffer(); + Offer memory offer = _createAndAcceptSingleAssetOffer(); bytes32 offerId = generateOfferId(offer); - vm.prank(account2); - echo.acceptOffer(offerId); - Offer memory updatedOffer = Offer({ sender: offer.sender, receiver: offer.receiver, @@ -121,41 +77,9 @@ contract AcceptOfferTest is BaseTest { } function testCanAcceptOfferMultipleAssets() public { - address[] memory senderTokenAddresses = new address[](2); - senderTokenAddresses[0] = apeAddress; - senderTokenAddresses[1] = apeAddress; - uint256[] memory senderTokenIds = new uint256[](2); - senderTokenIds[0] = ape1Id; - senderTokenIds[1] = ape2Id; - - address[] memory receiverTokenAddresses = new address[](2); - receiverTokenAddresses[0] = birdAddress; - receiverTokenAddresses[1] = birdAddress; - uint256[] memory receiverTokenIds = new uint256[](2); - receiverTokenIds[0] = bird1Id; - receiverTokenIds[1] = bird2Id; - - Offer memory offer = generateOffer( - account1, - senderTokenAddresses, - senderTokenIds, - block.chainid, - account2, - receiverTokenAddresses, - receiverTokenIds, - block.chainid, - in6hours, - OfferState.OPEN - ); - - vm.prank(account1); - echo.createOffer(offer); - + Offer memory offer = _createAndAcceptMultipleAssetsOffer(); bytes32 offerId = generateOfferId(offer); - vm.prank(account2); - echo.acceptOffer(offerId); - Offer memory updatedOffer = Offer({ sender: offer.sender, receiver: offer.receiver, diff --git a/test/Banker.t.sol b/test/Banker.t.sol index a17e1fb..faa3ad7 100644 --- a/test/Banker.t.sol +++ b/test/Banker.t.sol @@ -17,73 +17,45 @@ contract BankerTest is BaseTest { echo.setFees(0.005 ether); assertEq(echo.tradingFee(), 0.005 ether); } - // TODO Fix this once we have utils functions to execute a swap - // function testCannotWithdrawIfNotOwner() public { - // // Set fees - // vm.prank(owner); - // echo.setFees(0.005 ether); - // - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // _executeMockTrade("test", account1, account2, 0.005 ether); - // - // vm.prank(account1); - // vm.expectRevert("UNAUTHORIZED"); - // echo.withdraw(account1); - // } - // - // function testCanWithdrawToSelfIfOwner() public { - // // Set fees - // vm.prank(owner); - // echo.setFees(0.005 ether); - // - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // _executeMockTrade("test", account1, account2, 0.005 ether); - // - // assertEq(address(echo).balance, 0.005 ether); - // vm.prank(owner); - // echo.withdraw(owner); - // assertEq(owner.balance, 0.005 ether); - // assertEq(address(echo).balance, 0); - // } - // - // function testCanWithdrawToOtherAccountIfOwner() public { - // // Set fees - // vm.prank(owner); - // echo.setFees(0.005 ether); - // - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // _executeMockTrade("test", account1, account2, 0.005 ether); - // - // vm.prank(owner); - // echo.withdraw(account3); - // assertEq(account3.balance, 100 ether + 0.005 ether); - // assertEq(address(echo).balance, 0); - // } - // - // function testCannotWithdrawToContractIfOwner() public { - // // Set fees - // vm.prank(owner); - // echo.setFees(0.005 ether); - // - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // _executeMockTrade("test", account1, account2, 0.005 ether); - // - // vm.prank(owner); - // vm.expectRevert(WithdrawFailed.selector); - // echo.withdraw(address(echo)); - // assertEq(account3.balance, 100 ether); - // assertEq(address(echo).balance, 0.005 ether); - // } + + function testCannotWithdrawIfNotOwner() public { + _setFees(); + _executeSingleAssetOffer(); + + vm.prank(account1); + vm.expectRevert("UNAUTHORIZED"); + echo.withdraw(account1); + } + + function testCanWithdrawToSelfIfOwner() public { + _setFees(); + _executeSingleAssetOffer(); + + assertEq(address(echo).balance, echo.tradingFee() * 2); + vm.prank(owner); + echo.withdraw(owner); + assertEq(owner.balance, echo.tradingFee() + echo.tradingFee()); + assertEq(address(echo).balance, 0); + } + + function testCanWithdrawToOtherAccountIfOwner() public { + uint256 initialBalance = account3.balance; + _setFees(); + _executeSingleAssetOffer(); + + vm.prank(owner); + echo.withdraw(account3); + assertEq(account3.balance, initialBalance + echo.tradingFee() * 2); + assertEq(address(echo).balance, 0); + } + + function testCannotWithdrawToContractIfOwner() public { + _setFees(); + _executeSingleAssetOffer(); + + vm.prank(owner); + vm.expectRevert(WithdrawFailed.selector); + echo.withdraw(address(echo)); + assertEq(address(echo).balance, echo.tradingFee() * 2); + } } diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index 6dfc0cd..cad1013 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -2,21 +2,15 @@ pragma solidity ^0.8.18; import "./mock/Mocked721.sol"; -import "./mock/MockHandler.sol"; import "forge-std/Test.sol"; import "./utils/OfferUtils.sol"; -import "../src/EchoCrossChain.sol"; +import "../src/Echo.sol"; abstract contract BaseTest is Test, OfferUtils { // Exclude from coverage report function test() public override {} - EchoCrossChain public echo; - - // TODO Remove? - // To test internal function as it's impossible to reach the code - // from echo (echo also checks for length) - MockedHandler public handler; + Echo public echo; Mocked721 public apes; Mocked721 public birds; @@ -39,11 +33,6 @@ abstract contract BaseTest is Test, OfferUtils { uint256 public bird2Id; uint256 public bird3Id; - address[] public creator721Collections; - uint256[] public creator721Ids; - address[] public counterparty721Collections; - uint256[] public counterparty721Ids; - function setUp() public { // Generate account2 and signer from private key. account2 = vm.addr(account2PrivateKey); @@ -55,8 +44,7 @@ abstract contract BaseTest is Test, OfferUtils { vm.deal(account3, 100 ether); vm.deal(account4, 100 ether); - echo = new EchoCrossChain(address(owner)); - handler = new MockedHandler(); + echo = new Echo(address(owner)); apes = new Mocked721("Apes", "APE"); birds = new Mocked721("Birds", "BIRD"); @@ -89,7 +77,7 @@ abstract contract BaseTest is Test, OfferUtils { in6hours = block.timestamp + (60 * 60 * 6); } - function _createMockOffer() internal returns (Offer memory offer) { + function _createSingleAssetOffer() internal returns (Offer memory offer) { address[] memory senderTokenAddresses = new address[](1); senderTokenAddresses[0] = apeAddress; uint256[] memory senderTokenIds = new uint256[](1); @@ -115,38 +103,81 @@ abstract contract BaseTest is Test, OfferUtils { vm.prank(account1); echo.createOffer(offer); + vm.stopPrank(); + } + + function _createMultipleAssetsOffer() internal returns (Offer memory offer) { + address[] memory senderTokenAddresses = new address[](2); + senderTokenAddresses[0] = apeAddress; + senderTokenAddresses[1] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](2); + senderTokenIds[0] = ape1Id; + senderTokenIds[1] = ape2Id; + + address[] memory receiverTokenAddresses = new address[](2); + receiverTokenAddresses[0] = birdAddress; + receiverTokenAddresses[1] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](2); + receiverTokenIds[0] = bird1Id; + receiverTokenIds[1] = bird2Id; + + offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + echo.createOffer(offer); + vm.stopPrank(); + } + + function _createAndAcceptSingleAssetOffer() internal returns (Offer memory offer) { + uint256 tradingFee = echo.tradingFee(); + offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + echo.acceptOffer{value: tradingFee}(offerId); + vm.stopPrank(); + } + + function _createAndAcceptMultipleAssetsOffer() internal returns (Offer memory offer) { + uint256 tradingFee = echo.tradingFee(); + offer = _createMultipleAssetsOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + echo.acceptOffer{value: tradingFee}(offerId); + vm.stopPrank(); + } + + function _executeSingleAssetOffer() internal returns (Offer memory offer) { + uint256 tradingFee = echo.tradingFee(); + offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + echo.executeOffer{value: tradingFee}(offerId); + vm.stopPrank(); } function _setFees() internal { vm.prank(owner); echo.setFees(0.005 ether); + vm.stopPrank(); } function _setPaused() internal { vm.prank(owner); echo.setPaused(true); - } - - // @dev Method to execute a mock trade with predefined values - // @dev Do not use this method if you expect a revert as the way Foundry is built, it won't catch the revert - function _executeMockTrade(string memory id, address creator, address counter, uint256 fees) internal { - // Trade memory trade = Trade({ - // id: id, - // creator: creator, - // counterparty: counter, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // (uint8 v, bytes32 r, bytes32 s) = _signTrade(trade, account2PrivateKey); - // Signature memory signature = Signature({v: v, r: r, s: s}); - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner) = _signSignature( - // signature, - // signerPrivateKey - // ); - // vm.prank(creator); - // echo.executeTrade{value: fees}(vSigner, rSigner, sSigner, signature, trade); + vm.stopPrank(); } } diff --git a/test/CancelOffer.t.sol b/test/CancelOffer.t.sol new file mode 100644 index 0000000..c67012c --- /dev/null +++ b/test/CancelOffer.t.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; +import "./BaseTest.t.sol"; +import "../src/types/Offer.sol"; + +contract CancelOfferTest is BaseTest { + function testCannotCancelNonExistentOffer() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape2Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird2Id; + + Offer memory invalidOffer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + bytes32 offerId = generateOfferId(invalidOffer); + + vm.prank(account1); + vm.expectRevert(InvalidReceiver.selector); + echo.cancelOffer(offerId); + } + + function testCanCancelOfferSingleAsset() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + echo.cancelOffer(offerId); + + (address sender,,,,,) = echo.offers(offerId); + + // @dev When the offer is cancelled, it's also deleted + assertEq(sender, address(0)); + + // validate that the sender items are not in escrow + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + // validate that the receiver items are not in escrow + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + } + + function testCanCancelOfferMultipleAssets() public { + Offer memory offer = _createMultipleAssetsOffer(); + + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + echo.cancelOffer(offerId); + + (address sender,,,,,) = echo.offers(offerId); + + // @dev When the offer is cancelled, it's also deleted + assertEq(sender, address(0)); + + // validate that the sender items are not in escrow + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + // validate that the receiver items are not in escrow + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + } +} diff --git a/test/CreateOffer.t.sol b/test/CreateOffer.t.sol index 23bd4f5..b54a697 100644 --- a/test/CreateOffer.t.sol +++ b/test/CreateOffer.t.sol @@ -7,120 +7,6 @@ import "../src/types/OfferItems.sol"; import "../src/types/Offer.sol"; contract CreateOfferTest is BaseTest { - function testCannotCreateOfferIfPaused() public { - _setPaused(); - - address[] memory senderTokenAddresses = new address[](1); - senderTokenAddresses[0] = apeAddress; - uint256[] memory senderTokenIds = new uint256[](1); - senderTokenIds[0] = ape1Id; - - address[] memory receiverTokenAddresses = new address[](1); - receiverTokenAddresses[0] = birdAddress; - uint256[] memory receiverTokenIds = new uint256[](1); - receiverTokenIds[0] = bird1Id; - - Offer memory offer = generateOffer( - account1, - senderTokenAddresses, - senderTokenIds, - block.chainid, - account2, - receiverTokenAddresses, - receiverTokenIds, - block.chainid, - in6hours, - OfferState.OPEN - ); - - vm.prank(account1); - vm.expectRevert(Paused.selector); - echo.createOffer(offer); - } - - function testCannotCreateOfferIfAlreadyExpired() public { - address[] memory senderTokenAddresses = new address[](1); - senderTokenAddresses[0] = apeAddress; - uint256[] memory senderTokenIds = new uint256[](1); - senderTokenIds[0] = ape1Id; - - address[] memory receiverTokenAddresses = new address[](1); - receiverTokenAddresses[0] = birdAddress; - uint256[] memory receiverTokenIds = new uint256[](1); - receiverTokenIds[0] = bird1Id; - - Offer memory offer = generateOffer( - account1, - senderTokenAddresses, - senderTokenIds, - block.chainid, - account2, - receiverTokenAddresses, - receiverTokenIds, - block.chainid, - block.timestamp, - OfferState.OPEN - ); - - vm.prank(account1); - vm.expectRevert(OfferHasExpired.selector); - echo.createOffer(offer); - } - - function testCannotCreateOfferIfReceiverItemsIsEmpty() public { - address[] memory senderTokenAddresses = new address[](1); - senderTokenAddresses[0] = apeAddress; - uint256[] memory senderTokenIds = new uint256[](1); - senderTokenIds[0] = ape1Id; - - address[] memory receiverTokenAddresses = new address[](0); - uint256[] memory receiverTokenIds = new uint256[](0); - - Offer memory offer = generateOffer( - account1, - senderTokenAddresses, - senderTokenIds, - block.chainid, - account2, - receiverTokenAddresses, - receiverTokenIds, - block.chainid, - in6hours, - OfferState.OPEN - ); - - vm.prank(account1); - vm.expectRevert(InvalidAssets.selector); - echo.createOffer(offer); - } - - function testCannotCreateOfferIfSenderItemsIsEmpty() public { - address[] memory senderTokenAddresses = new address[](0); - uint256[] memory senderTokenIds = new uint256[](0); - - address[] memory receiverTokenAddresses = new address[](1); - receiverTokenAddresses[0] = birdAddress; - uint256[] memory receiverTokenIds = new uint256[](1); - receiverTokenIds[0] = bird1Id; - - Offer memory offer = generateOffer( - account1, - senderTokenAddresses, - senderTokenIds, - block.chainid, - account2, - receiverTokenAddresses, - receiverTokenIds, - block.chainid, - in6hours, - OfferState.OPEN - ); - - vm.prank(account1); - vm.expectRevert(InvalidAssets.selector); - echo.createOffer(offer); - } - function testCannotCreateOfferIfStateNotOpen() public { address[] memory senderTokenAddresses = new address[](1); senderTokenAddresses[0] = apeAddress; @@ -150,34 +36,6 @@ contract CreateOfferTest is BaseTest { echo.createOffer(offer); } - function testCannotCreateOfferIfNotSender() public { - address[] memory senderTokenAddresses = new address[](1); - senderTokenAddresses[0] = apeAddress; - uint256[] memory senderTokenIds = new uint256[](1); - senderTokenIds[0] = ape1Id; - - address[] memory receiverTokenAddresses = new address[](1); - receiverTokenAddresses[0] = birdAddress; - uint256[] memory receiverTokenIds = new uint256[](1); - receiverTokenIds[0] = bird1Id; - - Offer memory offer = generateOffer( - account1, - senderTokenAddresses, - senderTokenIds, - block.chainid, - account2, - receiverTokenAddresses, - receiverTokenIds, - block.chainid, - in6hours, - OfferState.OPEN - ); - - vm.prank(account2); - vm.expectRevert(InvalidSender.selector); - echo.createOffer(offer); - } // TODO Not sure if this case if even possible since the assets are deposited on an offer creation // so it's impossible to recreate the same offer ID // function testCannotCreateDuplicateOffer() public { @@ -212,7 +70,7 @@ contract CreateOfferTest is BaseTest { // } function testCanCreateOfferSingleAsset() public { - Offer memory offer = _createMockOffer(); + Offer memory offer = _createSingleAssetOffer(); // validate the offer id bytes32 offerId = generateOfferId(offer); @@ -243,35 +101,7 @@ contract CreateOfferTest is BaseTest { } function testCanCreateOfferMultipleAssets() public { - address[] memory senderTokenAddresses = new address[](2); - senderTokenAddresses[0] = apeAddress; - senderTokenAddresses[1] = apeAddress; - uint256[] memory senderTokenIds = new uint256[](2); - senderTokenIds[0] = ape1Id; - senderTokenIds[1] = ape2Id; - - address[] memory receiverTokenAddresses = new address[](2); - receiverTokenAddresses[0] = birdAddress; - receiverTokenAddresses[1] = birdAddress; - uint256[] memory receiverTokenIds = new uint256[](2); - receiverTokenIds[0] = bird1Id; - receiverTokenIds[1] = bird2Id; - - Offer memory offer = generateOffer( - account1, - senderTokenAddresses, - senderTokenIds, - block.chainid, - account2, - receiverTokenAddresses, - receiverTokenIds, - block.chainid, - in6hours, - OfferState.OPEN - ); - - vm.prank(account1); - echo.createOffer(offer); + Offer memory offer = _createMultipleAssetsOffer(); // validate the offer id bytes32 offerId = generateOfferId(offer); diff --git a/test/ExecuteOffer.t.sol b/test/ExecuteOffer.t.sol new file mode 100644 index 0000000..208f481 --- /dev/null +++ b/test/ExecuteOffer.t.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; +import "./BaseTest.t.sol"; +import "../src/types/Offer.sol"; + +contract ExecuteOfferTest is BaseTest { + function testCannotExecuteNonExistentOffer() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape2Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird2Id; + + Offer memory invalidOffer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + bytes32 offerId = generateOfferId(invalidOffer); + + vm.prank(account1); + vm.expectRevert(InvalidSender.selector); + echo.executeOffer(offerId); + } + + function testCannotExecuteOfferIfNotAccepted() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + vm.expectRevert("WRONG_FROM"); + echo.executeOffer(offerId); + } + + function testCanExecuteOfferSingleAsset() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + echo.executeOffer(offerId); + + (address sender,,,,,) = echo.offers(offerId); + + // @dev When the offer is executed, it's also deleted + assertEq(sender, address(0)); + + // validate that the sender items are swapped + assertOfferItemsOwnership(offer.senderItems.items, offer.receiver); + // validate that the receiver items are swapped + assertOfferItemsOwnership(offer.receiverItems.items, offer.sender); + } + + function testCanExecuteOfferMultipleAssets() public { + Offer memory offer = _createAndAcceptMultipleAssetsOffer(); + + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + echo.executeOffer(offerId); + + (address sender,,,,,) = echo.offers(offerId); + + // @dev When the offer is executed, it's also deleted + assertEq(sender, address(0)); + + // validate that the sender items are swapped + assertOfferItemsOwnership(offer.senderItems.items, offer.receiver); + // validate that the receiver items are swapped + assertOfferItemsOwnership(offer.receiverItems.items, offer.sender); + } +} diff --git a/test/Expiration.t.sol b/test/Expiration.t.sol index 53f2c1f..088ba15 100644 --- a/test/Expiration.t.sol +++ b/test/Expiration.t.sol @@ -6,51 +6,62 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract ExpirationTest is BaseTest { -// function testExpiresAtCurrentBlock() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// uint256 expired = block.timestamp; -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: expired, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(TradeHasExpired.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -// -// function testExpiresBeforeCurrentBlock() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// uint256 expired = block.timestamp - 1; -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: expired, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(TradeHasExpired.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } + function testCannotCreateOfferIfAlreadyExpired() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + block.timestamp, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(OfferHasExpired.selector); + echo.createOffer(offer); + } + + function testCannotCancelOfferIfAlreadyExpired() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.warp(in6hours); + vm.prank(account1); + vm.expectRevert(OfferHasExpired.selector); + echo.cancelOffer(offerId); + } + + function testCannotAcceptOfferIfAlreadyExpired() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.warp(in6hours); + vm.prank(account2); + vm.expectRevert(OfferHasExpired.selector); + echo.acceptOffer(offerId); + } + + function testCannotExecuteOfferIfAlreadyExpired() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.warp(in6hours); + vm.prank(account1); + vm.expectRevert(OfferHasExpired.selector); + echo.executeOffer(offerId); + } } diff --git a/test/Fees.t.sol b/test/Fees.t.sol index 59f2de6..1961839 100644 --- a/test/Fees.t.sol +++ b/test/Fees.t.sol @@ -2,70 +2,38 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract FeesTest is BaseTest { -// function testRevertsWithoutFunds() public { -// // Set fees -// vm.prank(owner); -// echo.setFees(0.005 ether); -// -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(InvalidPayment.selector); -// // 0 ether -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// vm.prank(account1); -// vm.expectRevert(InvalidPayment.selector); -// // Not enough ether -// echo.executeTrade{value: 0.004 ether}(vSigner, rSigner, sSigner, signature, trade); -// } -// -// function testSucceedsWithFunds() public { -// // Set fees -// vm.prank(owner); -// echo.setFees(0.005 ether); -// -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// echo.executeTrade{value: 0.005 ether}(vSigner, rSigner, sSigner, signature, trade); -// assertEq(address(echo).balance, 0.005 ether); -// assertEq(account1.balance, 100 ether - 0.005 ether); -// } + function testCannotAcceptOfferIfNotEnoughFunds() public { + _setFees(); + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + vm.expectRevert(InvalidPayment.selector); + echo.acceptOffer(offerId); + } + + function testCannotExecuteOfferIfNotEnoughFunds() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + _setFees(); + + vm.prank(account1); + vm.expectRevert(InvalidPayment.selector); + echo.executeOffer(offerId); + } + + function testCanExecuteOfferIfEnoughFunds() public { + uint256 initialAccount1Balance = account1.balance; + uint256 initialAccount2Balance = account2.balance; + _setFees(); + _executeSingleAssetOffer(); + + assertEq(account1.balance, initialAccount1Balance - echo.tradingFee()); + assertEq(account2.balance, initialAccount2Balance - echo.tradingFee()); + assertEq(address(echo).balance, echo.tradingFee() + echo.tradingFee()); + } } diff --git a/test/Handler.t.sol b/test/Handler.t.sol deleted file mode 100644 index 50c1457..0000000 --- a/test/Handler.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "./BaseTest.t.sol"; -import "forge-std/Test.sol"; - -contract HandlerTest is BaseTest { -// function testIdsLonger() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// creator721Ids.push(ape2Id); -// -// vm.expectRevert(LengthMismatch.selector); -// handler.transferTokens(creator721Collections, creator721Ids, account1, account2); -// -// // Assets are not swapped -// assertEq(apes.ownerOf(1), account1); -// assertEq(apes.ownerOf(2), account1); -// } -// -// function testCollectionsLonger() public { -// creator721Collections.push(apeAddress); -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape2Id); -// -// vm.expectRevert(LengthMismatch.selector); -// handler.transferTokens(creator721Collections, creator721Ids, account1, account2); -// // Assets are not swapped -// assertEq(apes.ownerOf(2), account1); -// } -} diff --git a/test/Ownership.t.sol b/test/Ownership.t.sol index 2dc96f5..295937a 100644 --- a/test/Ownership.t.sol +++ b/test/Ownership.t.sol @@ -6,97 +6,59 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract OwnershipTest is BaseTest { - // Sender is not creator - function testCannotCreateOfferIfNotCreator() public { - senderItems.push(OfferItem({tokenAddress: apeAddress, tokenId: ape1Id})); - receiverItems.push(OfferItem({tokenAddress: birdAddress, tokenId: bird1Id})); + function testCannotCreateOfferIfNotSender() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; - Offer memory offer = Offer({ - sender: account1, - receiver: account2, - senderItems: OfferItems({chainId: block.chainid, items: senderItems}), - receiverItems: OfferItems({chainId: block.chainid, items: receiverItems}), - expiration: in6hours, - state: OfferState.OPEN - }); + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account2); + vm.expectRevert(InvalidSender.selector); + echo.createOffer(offer); + } + + function testCannotCancelOfferIfNotSender() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account3); + vm.expectRevert(InvalidReceiver.selector); + echo.cancelOffer(offerId); + } + + function testCannotAcceptOfferIfNotReceiver() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account3); + vm.expectRevert(InvalidReceiver.selector); + echo.acceptOffer(offerId); + } + + function testCannotExecuteOfferIfNotSender() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + vm.expectRevert(InvalidSender.selector); + echo.executeOffer(offerId); } - // function testCannotExecuteTradeIfNotCreator() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // // Counterparty - // vm.prank(account2); - // vm.expectRevert(InvalidCreator.selector); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // - // // Random account - // vm.prank(account3); - // vm.expectRevert(InvalidCreator.selector); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // } - // - // // Creator is not owner - // function testCannotExecuteTradeIfCreatorNotOwner() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account3, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account3); - // vm.expectRevert(bytes("WRONG_FROM")); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // } - // - // // TODO Should be the same error message as the other? - // // Counterparty is not owner - // function testCannotExecuteTradeIfCounterpartyNotOwner() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird3Id); - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert(bytes("WRONG_FROM")); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // } } diff --git a/test/Paused.t.sol b/test/Paused.t.sol new file mode 100644 index 0000000..b995049 --- /dev/null +++ b/test/Paused.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "./BaseTest.t.sol"; +import "./mock/Mocked721.sol"; +import "forge-std/Test.sol"; + +contract PausedTest is BaseTest { + function testCannotCreateOfferIfPaused() public { + _setPaused(); + + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(Paused.selector); + echo.createOffer(offer); + } + + function testCannotAcceptOfferIfPaused() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + _setPaused(); + + vm.prank(account2); + vm.expectRevert(Paused.selector); + echo.acceptOffer(offerId); + } + + function testCannotCancelOfferIfPaused() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + _setPaused(); + + vm.prank(account1); + vm.expectRevert(Paused.selector); + echo.cancelOffer(offerId); + } + + function testCannotExecuteOfferIfPaused() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + _setPaused(); + + vm.prank(account1); + vm.expectRevert(Paused.selector); + echo.executeOffer(offerId); + } +} diff --git a/test/TestBridge.t.sol b/test/TestBridge.t.sol deleted file mode 100644 index 26d1076..0000000 --- a/test/TestBridge.t.sol +++ /dev/null @@ -1,169 +0,0 @@ -// SPDX-License-Identifier: Apache 2 -pragma solidity ^0.8.18; -// -//import "./utils/WormholeSimulator.sol"; -//import "./utils/EchoCrossChainTest.sol"; -//import "contracts/wormhole/WormholeData.sol"; -//import "contracts/wormhole/WormholeError.sol"; -//import "forge-std/Test.sol"; -//import "forge-std/console.sol"; -//import "solmate/test/utils/mocks/MockERC721.sol"; -// -///** -// * @title A Test Suite for the EVM EchoCrossChain Contracts -// */ -//contract TestBridge is Test { -// // guardian private key for simulated signing of Wormhole messages -// uint256 guardianSigner; -// -// // contract instances -// IWormhole wormhole; -// WormholeSimulator wormholeSimulator; -// EchoCrossChainTest echoSource; -// EchoCrossChainTest echoTarget; -// -// address public constant owner = address(1313); -// address public constant sender = address(1337); -// address public constant receiver = address(1339); -// -// MockERC721 public apes; -// MockERC721 public birds; -// -// address public apeAddress; -// uint256 public ape1Id; -// address public birdAddress; -// uint256 public bird1Id; -// -// /** -// * @notice Sets up the wormholeSimulator contracts and deploys HelloWorld -// * contracts before each test is executed. -// */ -// function setUp() public { -// vm.deal(sender, 100 ether); -// vm.deal(receiver, 100 ether); -// -// apes = new MockERC721("Apes", "APE"); -// birds = new MockERC721("Birds", "BIRD"); -// -// apes.safeMint(sender, 1); -// birds.safeMint(receiver, 1); -// -// /* Initialize wormhole */ -// // verify that we're using the correct fork (AVAX mainnet in this case) -// require(block.chainid == vm.envUint("TESTING_AVAX_FORK_CHAINID"), "wrong evm"); -// -// // this will be used to sign Wormhole messages -// guardianSigner = uint256(vm.envBytes32("TESTING_DEVNET_GUARDIAN")); -// -// // we may need to interact with Wormhole throughout the test -// wormhole = IWormhole(vm.envAddress("TESTING_AVAX_WORMHOLE_ADDRESS")); -// -// // set up Wormhole using Wormhole existing on AVAX mainnet -// wormholeSimulator = new SigningWormholeSimulator(wormhole, guardianSigner); -// -// // verify Wormhole state from fork -// require( -// wormhole.chainId() == uint16(vm.envUint("TESTING_AVAX_WORMHOLE_CHAINID")), -// "wrong chainId" -// ); -// require( -// wormhole.messageFee() == vm.envUint("TESTING_AVAX_WORMHOLE_MESSAGE_FEE"), -// "wrong messageFee" -// ); -// require( -// wormhole.getCurrentGuardianSetIndex() == -// uint32(vm.envUint("TESTING_AVAX_WORMHOLE_GUARDIAN_SET_INDEX")), -// "wrong guardian set index" -// ); -// -// echoSource = new EchoCrossChainTest( -// address(owner), -// address(wormhole), -// wormhole.chainId(), -// uint8(1) -// ); -// echoTarget = new EchoCrossChainTest(address(owner), address(wormhole), uint8(2), uint8(1)); -// -// // confirm that the source and target contract addresses are different -// assertTrue(address(echoSource) != address(echoTarget)); -// } -// -// function testTransfer() public { -// assertEq(birds.ownerOf(1), receiver); -// vm.prank(receiver); -// birds.safeTransferFrom(receiver, address(echoTarget), 1); -// assertEq(birds.ownerOf(1), address(echoTarget)); -// } -// -// function testAcceptTrade() public { -// // start listening to events -// vm.recordLogs(); -// -// bytes32 evmSender = bytes32(uint256(uint160(sender)) << 96); -// bytes32 evmReceiver = bytes32(uint256(uint160(receiver)) << 96); -// bytes32 evmTokenAddress = bytes32(uint256(uint160(address(birds))) << 96); -// uint64 evmTokenId = uint64(1); -// bytes32 solSender = bytes32(0); -// bytes32 solReceiver = bytes32(0); -// bytes32 solSenderTokenMint = bytes32(0); -// -// EchoMessageWithoutPayload memory message = EchoMessageWithoutPayload({ -// id: "test", -// evmSender: evmSender, -// evmReceiver: evmReceiver, -// evmTokenAddress: evmTokenAddress, -// evmTokenId: evmTokenId, -// solSender: solSender, -// solReceiver: solReceiver, -// solSenderTokenMint: solSenderTokenMint -// }); -// echoTarget.sendMessage(message); -// -// // record the emitted wormhole message -// Vm.Log[] memory entries = vm.getRecordedLogs(); -// -// // simulate signing the Wormhole message -// // NOTE: in the wormhole-sdk, signed Wormhole messages are referred to as signed VAAs -// bytes memory encodedMessage = wormholeSimulator.fetchSignedMessageFromLogs( -// entries[0], -// echoTarget.chainId(), -// address(echoTarget) -// ); -// -// vm.startPrank(owner); -// // register the emitter on the source contract -// echoSource.registerEmitter( -// echoTarget.chainId(), -// bytes32(uint256(uint160(address(echoTarget)))) -// ); -// vm.stopPrank(); -// -// vm.startPrank(receiver); -// birds.approve(address(echoSource), 1); -// echoSource.acceptOffer( -// "test", -// Offer({ -// sender: sender, -// receiver: receiver, -// expiresAt: block.timestamp + (60 * 60 * 6), -// status: OfferStatus.Created, -// receiver721Asset: ERC721Asset({collection: address(birds), id: evmTokenId}) -// }), -// encodedMessage -// ); -// -// // Parse the encodedMessage to retrieve the hash. This is a safe operation -// // since the source HelloWorld contract already verfied the message in the -// // previous call. -// IWormhole.VM memory parsedMessage = wormhole.parseVM(encodedMessage); -// -// // Verify that the message was consumed and the payload was saved -// // in the contract state. -// bool messageWasConsumed = echoSource.isMessageConsumed(parsedMessage.hash); -// -// assertTrue(messageWasConsumed); -// -// vm.expectRevert(MessageAlreadyConsumed.selector); -// echoSource.receiveMessage(encodedMessage); -// } -//} diff --git a/test/WrongAssets.t.sol b/test/WrongAssets.t.sol index 61b56bd..1da1781 100644 --- a/test/WrongAssets.t.sol +++ b/test/WrongAssets.t.sol @@ -5,246 +5,277 @@ import "./BaseTest.t.sol"; import "forge-std/Test.sol"; contract WrongAssetsTest is BaseTest { -// function testCannotSwapEmptyCreatorAssets() public { -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird2Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(InvalidAssets.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -// -// function testCannotSwapEmptyCounterpartyAssets() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(InvalidAssets.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -// -// function testCannotSwapEmptyAssets() public { -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(InvalidAssets.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -// -// function testCannotTradeLongerCreatorIds() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// creator721Ids.push(ape2Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(LengthMismatch.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are not swapped -// assertEq(apes.ownerOf(1), account1); -// assertEq(apes.ownerOf(2), account1); -// assertEq(birds.ownerOf(1), account2); -// } -// -// function testCannotTradeLongerCreatorCollections() public { -// creator721Collections.push(apeAddress); -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(LengthMismatch.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are not swapped -// assertEq(apes.ownerOf(1), account1); -// assertEq(birds.ownerOf(1), account2); -// } -// -// function testCannotTradeLongerCounterpartyIds() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// counterparty721Ids.push(bird2Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(LengthMismatch.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are not swapped -// assertEq(apes.ownerOf(1), account1); -// assertEq(birds.ownerOf(1), account2); -// assertEq(birds.ownerOf(2), account2); -// } -// -// function testCannotTradeLongerCounterpartyCollections() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(LengthMismatch.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are not swapped -// assertEq(apes.ownerOf(1), account1); -// assertEq(birds.ownerOf(1), account2); -// } -// -// function testCannotTradeSameCreatorAssets() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert("WRONG_FROM"); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are not swapped -// assertEq(apes.ownerOf(1), account1); -// assertEq(birds.ownerOf(1), account2); -// } -// -// function testCannotTradeSameCounterpartyAssets() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert("WRONG_FROM"); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are not swapped -// assertEq(apes.ownerOf(1), account1); -// assertEq(birds.ownerOf(1), account2); -// } + function testCannotCreateOfferIfReceiverItemsIsEmpty() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](0); + uint256[] memory receiverTokenIds = new uint256[](0); + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(InvalidAssets.selector); + echo.createOffer(offer); + } + + function testCannotCreateOfferIfSenderItemsIsEmpty() public { + address[] memory senderTokenAddresses = new address[](0); + uint256[] memory senderTokenIds = new uint256[](0); + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(InvalidAssets.selector); + echo.createOffer(offer); + } + + // + // function testCannotSwapEmptyCounterpartyAssets() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert(InvalidAssets.selector); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // } + // + // function testCannotSwapEmptyAssets() public { + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert(InvalidAssets.selector); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // } + // + // function testCannotTradeLongerCreatorIds() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // creator721Ids.push(ape2Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert(LengthMismatch.selector); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // + // // Assets are not swapped + // assertEq(apes.ownerOf(1), account1); + // assertEq(apes.ownerOf(2), account1); + // assertEq(birds.ownerOf(1), account2); + // } + // + // function testCannotTradeLongerCreatorCollections() public { + // creator721Collections.push(apeAddress); + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert(LengthMismatch.selector); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // + // // Assets are not swapped + // assertEq(apes.ownerOf(1), account1); + // assertEq(birds.ownerOf(1), account2); + // } + // + // function testCannotTradeLongerCounterpartyIds() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // counterparty721Ids.push(bird2Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert(LengthMismatch.selector); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // + // // Assets are not swapped + // assertEq(apes.ownerOf(1), account1); + // assertEq(birds.ownerOf(1), account2); + // assertEq(birds.ownerOf(2), account2); + // } + // + // function testCannotTradeLongerCounterpartyCollections() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert(LengthMismatch.selector); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // + // // Assets are not swapped + // assertEq(apes.ownerOf(1), account1); + // assertEq(birds.ownerOf(1), account2); + // } + // + // function testCannotTradeSameCreatorAssets() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert("WRONG_FROM"); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // + // // Assets are not swapped + // assertEq(apes.ownerOf(1), account1); + // assertEq(birds.ownerOf(1), account2); + // } + // + // function testCannotTradeSameCounterpartyAssets() public { + // creator721Collections.push(apeAddress); + // creator721Ids.push(ape1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // counterparty721Collections.push(birdAddress); + // counterparty721Ids.push(bird1Id); + // + // Trade memory trade = Trade({ + // id: "test", + // creator: account1, + // counterparty: account2, + // expiresAt: in6hours, + // creatorCollections: creator721Collections, + // creatorIds: creator721Ids, + // counterpartyCollections: counterparty721Collections, + // counterpartyIds: counterparty721Ids + // }); + // + // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = + // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); + // vm.prank(account1); + // vm.expectRevert("WRONG_FROM"); + // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); + // + // // Assets are not swapped + // assertEq(apes.ownerOf(1), account1); + // assertEq(birds.ownerOf(1), account2); + // } } diff --git a/test/mock/MockHandler.sol b/test/mock/MockHandler.sol deleted file mode 100644 index 94485cc..0000000 --- a/test/mock/MockHandler.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "../../src/escrow/EscrowHandler.sol"; - -contract MockedHandler is EscrowHandler { - // Exclude from coverage report - function test() public {} -} From df4ce00721df4bbccd0686b2a71a1620888145e4 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 14:11:43 -0400 Subject: [PATCH 16/28] Added redeem --- src/Echo.sol | 24 ++++- test/Expiration.t.sol | 36 ++++++++ test/Ownership.t.sol | 18 ++++ test/RedeemOffer.t.sol | 203 +++++++++++++++++++++++++++++++++++++++++ test/Trade721.t.sol | 142 ---------------------------- 5 files changed, 280 insertions(+), 143 deletions(-) create mode 100644 test/RedeemOffer.t.sol delete mode 100644 test/Trade721.t.sol diff --git a/src/Echo.sol b/src/Echo.sol index 25a9a7a..ed468fd 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.18; import "solmate/utils/ReentrancyGuard.sol"; +import "solmate/tokens/ERC721.sol"; import "./Admin.sol"; import "./Banker.sol"; import "./EchoError.sol"; @@ -79,6 +80,7 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { function redeemOffer(bytes32 offerId) external nonReentrant notPaused { Offer memory offer = offers[offerId]; + // @dev no need to check for existence of offer because if deleted, the offer data points to 0 if (msg.sender != offer.sender && msg.sender != offer.receiver) { revert InvalidRecipient(); } @@ -87,11 +89,31 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { revert OfferHasNotExpired(); } - // @dev We know sender is either sender or receiver here, no need to check both + // @dev If sender, we need extra checks to make sure receiver also redeemed if offer was accepted if (msg.sender == offer.sender) { _withdraw(offer.senderItems, offer.sender); + + // @dev Receiver has escrowed only if offer was accepted + if (offer.state == OfferState.ACCEPTED) { + OfferItem memory receiverFirstOfferItem = offer.receiverItems.items[0]; + ERC721 receiverFirstNft = ERC721(receiverFirstOfferItem.tokenAddress); + // @dev if Echo is not the owner, it means receiver has redeemed + if (receiverFirstNft.ownerOf(receiverFirstOfferItem.tokenId) != address(this)) { + delete offers[offerId]; + } + // @dev If offer was OPEN, receiver has not escrowed, we can safely delete + } else { + delete offers[offerId]; + } } else { _withdraw(offer.receiverItems, offer.receiver); + // @dev We need to check if sender has redeemed too + OfferItem memory senderFirstOfferItem = offer.senderItems.items[0]; + ERC721 senderFirstNft = ERC721(senderFirstOfferItem.tokenAddress); + // @dev if Echo is not the owner, it means sender has redeemed + if (senderFirstNft.ownerOf(senderFirstOfferItem.tokenId) != address(this)) { + delete offers[offerId]; + } } } } diff --git a/test/Expiration.t.sol b/test/Expiration.t.sol index 088ba15..83254c5 100644 --- a/test/Expiration.t.sol +++ b/test/Expiration.t.sol @@ -64,4 +64,40 @@ contract ExpirationTest is BaseTest { vm.expectRevert(OfferHasExpired.selector); echo.executeOffer(offerId); } + + function testSenderCannotRedeemOpenOfferIfNotExpired() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + vm.expectRevert(OfferHasNotExpired.selector); + echo.redeemOffer(offerId); + } + + function testReceiverCannotRedeemOpenOfferIfNotExpired() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + vm.expectRevert(OfferHasNotExpired.selector); + echo.redeemOffer(offerId); + } + + function testSenderCannotRedeemAcceptedOfferIfNotExpired() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + vm.expectRevert(OfferHasNotExpired.selector); + echo.redeemOffer(offerId); + } + + function testReceiverCannotRedeemAcceptedOfferIfNotExpired() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + vm.expectRevert(OfferHasNotExpired.selector); + echo.redeemOffer(offerId); + } } diff --git a/test/Ownership.t.sol b/test/Ownership.t.sol index 295937a..1cb0c69 100644 --- a/test/Ownership.t.sol +++ b/test/Ownership.t.sol @@ -61,4 +61,22 @@ contract OwnershipTest is BaseTest { vm.expectRevert(InvalidSender.selector); echo.executeOffer(offerId); } + + function testCannotRedeemOpenOfferIfNotSenderOrReceiver() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account3); + vm.expectRevert(InvalidRecipient.selector); + echo.redeemOffer(offerId); + } + + function testCannotRedeemAcceptedOfferIfNotSenderOrReceiver() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account3); + vm.expectRevert(InvalidRecipient.selector); + echo.redeemOffer(offerId); + } } diff --git a/test/RedeemOffer.t.sol b/test/RedeemOffer.t.sol new file mode 100644 index 0000000..96785c1 --- /dev/null +++ b/test/RedeemOffer.t.sol @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; +import "./BaseTest.t.sol"; +import "../src/types/OfferItems.sol"; +import "../src/types/Offer.sol"; + +contract RedeemOfferTest is BaseTest { + function testSenderCannotRedeemOpenOfferTwice() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + // validate that the sender items are escrowed + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + + vm.warp(in6hours); + vm.prank(account1); + echo.redeemOffer(offerId); + + // validate that the sender items are redemeed + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + + (address sender,,,,,) = echo.offers(offerId); + + // @dev When the offer is redeemed, it's also deleted + assertEq(sender, address(0)); + + vm.prank(account1); + vm.expectRevert(InvalidRecipient.selector); + echo.redeemOffer(offerId); + } + + function testSenderCannotRedeemAcceptedOfferTwice() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + // validate that the sender items are escrowed + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + + vm.warp(in6hours); + vm.prank(account1); + echo.redeemOffer(offerId); + + // validate that the sender items are redemeed + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + + (address sender,,,,,) = echo.offers(offerId); + + // @dev Offer is still existing because receiver has not redeemed + assertEq(sender, offer.sender); + + vm.prank(account1); + // @dev withdraw fails + vm.expectRevert("WRONG_FROM"); + echo.redeemOffer(offerId); + } + + function testReceiverCannotRedeemAcceptedOfferTwice() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + // validate that the receiver items are escrowed + assertOfferItemsOwnership(offer.receiverItems.items, address(echo)); + + vm.warp(in6hours); + vm.prank(account2); + echo.redeemOffer(offerId); + + // validate that the receiver items are redemeed + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + + (, address receiver,,,,) = echo.offers(offerId); + + // @dev Offer is still existing because sender has not redeemed + assertEq(receiver, offer.receiver); + + vm.prank(account2); + // @dev withdraw fails + vm.expectRevert("WRONG_FROM"); + echo.redeemOffer(offerId); + } + + function testSenderCanRedeemExpiredOpenOffer() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + // validate that the sender items are escrowed + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + + vm.warp(in6hours); + vm.prank(account1); + echo.redeemOffer(offerId); + + // validate that the sender items are redemeed + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + + (address sender,,,,,) = echo.offers(offerId); + + // @dev When the offer is redeemed, it's also deleted + assertEq(sender, address(0)); + } + + function testSenderCanRedeemExpiredAcceptedOffer() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + // validate that the sender items are escrowed + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + + vm.warp(in6hours); + vm.prank(account1); + echo.redeemOffer(offerId); + + // validate that the sender items are redemeed + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + + (address sender,,,,,) = echo.offers(offerId); + + // @dev Offer is still existing because receiver has not redeemed + assertEq(sender, offer.sender); + } + + function testReceiverCanRedeemExpiredAcceptedOffer() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + // validate that the receiver items are escrowed + assertOfferItemsOwnership(offer.receiverItems.items, address(echo)); + + vm.warp(in6hours); + vm.prank(account2); + echo.redeemOffer(offerId); + + // validate that the receiver items are redemeed + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + + (, address receiver,,,,) = echo.offers(offerId); + + // @dev Offer is still existing because sender has not redeemed + assertEq(receiver, offer.receiver); + } + + function testExpiredAcceptedOfferIsDeletedWhenFullyRedeemedReceiverFirst() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + // validate that the receiver items are escrowed + assertOfferItemsOwnership(offer.receiverItems.items, address(echo)); + + vm.warp(in6hours); + vm.prank(account2); + echo.redeemOffer(offerId); + + // validate that the receiver items are redemeed + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + + (, address receiver,,,,) = echo.offers(offerId); + + // @dev Offer is still existing because sender has not redeemed + assertEq(receiver, offer.receiver); + + vm.prank(account1); + echo.redeemOffer(offerId); + + // validate that the sender items are redemeed + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + + (address sender,,,,,) = echo.offers(offerId); + // @dev When the offer is redeemed, it's also deleted + assertEq(sender, address(0)); + } + + function testExpiredAcceptedOfferIsDeletedWhenFullyRedeemedSenderFirst() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.warp(in6hours); + vm.prank(account1); + echo.redeemOffer(offerId); + + // validate that the sender items are redemeed + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + + (, address receiver,,,,) = echo.offers(offerId); + + // @dev Offer is still existing because sender has not redeemed + assertEq(receiver, offer.receiver); + + // validate that the receiver items are escrowed + assertOfferItemsOwnership(offer.receiverItems.items, address(echo)); + + vm.prank(account2); + echo.redeemOffer(offerId); + + // validate that the receiver items are redemeed + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + + (address sender,,,,,) = echo.offers(offerId); + // @dev When the offer is redeemed, it's also deleted + assertEq(sender, address(0)); + } +} diff --git a/test/Trade721.t.sol b/test/Trade721.t.sol deleted file mode 100644 index ff231ea..0000000 --- a/test/Trade721.t.sol +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -import "./BaseTest.t.sol"; -import "./mock/Mocked721.sol"; -import "forge-std/Test.sol"; - -contract Trade721Test is BaseTest { -// @dev Swap: 1 ape for 2 birds -// function testSwapOneForTwo() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird2Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// -// vm.prank(account1); -// vm.expectEmit(true, true, true, true); -// emit TradeExecuted("test"); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are now swapped -// assertEq(apes.ownerOf(1), account2); -// assertEq(birds.ownerOf(1), account1); -// assertEq(birds.ownerOf(2), account1); -// } -// -// // @dev Swap: 2 apes for 1 bird -// function testSwapTwoForOne() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape2Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectEmit(true, true, true, true); -// emit TradeExecuted("test"); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are now swapped -// assertEq(apes.ownerOf(1), account2); -// assertEq(apes.ownerOf(2), account2); -// assertEq(birds.ownerOf(1), account1); -// } -// -// // @dev Swap: 2 apes for 2 birds -// function testSwapTwoForTwo() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape2Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird2Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectEmit(true, true, true, true); -// emit TradeExecuted("test"); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are now swapped -// assertEq(apes.ownerOf(1), account2); -// assertEq(apes.ownerOf(2), account2); -// assertEq(birds.ownerOf(1), account1); -// assertEq(birds.ownerOf(2), account1); -// } -// -// function testCannotReuseTradeId() public { -// // Execute initial swap -// testSwapTwoForTwo(); -// -// // Second swap with same Id -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape2Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird2Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(TradeAlreadyExist.selector); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -} From a022ccb42ea659413952c0d7080135c8527094d4 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 14:23:29 -0400 Subject: [PATCH 17/28] Added creation paused function --- src/Admin.sol | 16 ++++++-- src/Banker.sol | 3 +- src/Echo.sol | 2 +- src/EchoError.sol | 3 ++ test/Admin.t.sol | 21 ++++++++++- test/Banker.t.sol | 1 - test/BaseTest.t.sol | 8 +++- test/Expiration.t.sol | 1 - test/Ownership.t.sol | 1 - test/Paused.t.sol | 88 ++++++++++++++++++++++++++++++++++++++++++- 10 files changed, 131 insertions(+), 13 deletions(-) diff --git a/src/Admin.sol b/src/Admin.sol index 268fb33..e9834cd 100644 --- a/src/Admin.sol +++ b/src/Admin.sol @@ -2,13 +2,12 @@ pragma solidity ^0.8.18; import "solmate/auth/Owned.sol"; - -error Paused(); -error InvalidAddress(); +import "./EchoError.sol"; /// @dev Handles ownable and pausable of contract. abstract contract Admin is Owned { bool public paused; + bool public creationPaused; constructor(address owner) Owned(owner) {} @@ -16,10 +15,21 @@ abstract contract Admin is Owned { paused = _paused; } + function setCreationPaused(bool _creationPaused) external onlyOwner { + creationPaused = _creationPaused; + } + modifier notPaused() { if (paused) { revert Paused(); } _; } + + modifier creationNotPaused() { + if (creationPaused) { + revert CreationPaused(); + } + _; + } } diff --git a/src/Banker.sol b/src/Banker.sol index 05d5528..2143530 100644 --- a/src/Banker.sol +++ b/src/Banker.sol @@ -2,8 +2,7 @@ pragma solidity ^0.8.18; import "solmate/auth/Owned.sol"; - -error WithdrawFailed(); +import "./EchoError.sol"; abstract contract Banker is Owned { uint256 public tradingFee = 0 ether; diff --git a/src/Echo.sol b/src/Echo.sol index ed468fd..1d5bf73 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -21,7 +21,7 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { /** * Same chain offers */ - function createOffer(Offer calldata offer) external nonReentrant notPaused { + function createOffer(Offer calldata offer) external nonReentrant notPaused creationNotPaused { // @dev Cannot accept an offer if not the receiver if (offer.sender != msg.sender) { revert InvalidSender(); diff --git a/src/EchoError.sol b/src/EchoError.sol index a0a5d57..e147355 100644 --- a/src/EchoError.sol +++ b/src/EchoError.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; +error CreationPaused(); error InvalidAssets(); error InvalidOfferState(); error InvalidPayment(); @@ -11,3 +12,5 @@ error OfferAlreadyExist(); error OfferDoesNotExist(); error OfferHasExpired(); error OfferHasNotExpired(); +error Paused(); +error WithdrawFailed(); diff --git a/test/Admin.t.sol b/test/Admin.t.sol index 6cc67b8..42f8fc8 100644 --- a/test/Admin.t.sol +++ b/test/Admin.t.sol @@ -10,8 +10,7 @@ contract AdminTest is BaseTest { vm.expectRevert("UNAUTHORIZED"); echo.setPaused(true); - vm.expectRevert("UNAUTHORIZED"); - echo.setPaused(false); + assertEq(echo.paused(), false); } function testCanPauseIfOwner() public { @@ -23,4 +22,22 @@ contract AdminTest is BaseTest { echo.setPaused(false); assertEq(echo.paused(), false); } + + function testCannotPauseCreationIfNotOwner() public { + vm.prank(account1); + vm.expectRevert("UNAUTHORIZED"); + echo.setCreationPaused(true); + + assertEq(echo.creationPaused(), false); + } + + function testCanPauseCreationIfOwner() public { + vm.prank(owner); + echo.setCreationPaused(true); + assertEq(echo.creationPaused(), true); + + vm.prank(owner); + echo.setCreationPaused(false); + assertEq(echo.creationPaused(), false); + } } diff --git a/test/Banker.t.sol b/test/Banker.t.sol index faa3ad7..2cafccc 100644 --- a/test/Banker.t.sol +++ b/test/Banker.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract BankerTest is BaseTest { diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index cad1013..b8b3679 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; -import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; +import "./mock/Mocked721.sol"; import "./utils/OfferUtils.sol"; import "../src/Echo.sol"; @@ -180,4 +180,10 @@ abstract contract BaseTest is Test, OfferUtils { echo.setPaused(true); vm.stopPrank(); } + + function _setCreationPaused() internal { + vm.prank(owner); + echo.setCreationPaused(true); + vm.stopPrank(); + } } diff --git a/test/Expiration.t.sol b/test/Expiration.t.sol index 83254c5..7b9d47c 100644 --- a/test/Expiration.t.sol +++ b/test/Expiration.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract ExpirationTest is BaseTest { diff --git a/test/Ownership.t.sol b/test/Ownership.t.sol index 1cb0c69..a9d2156 100644 --- a/test/Ownership.t.sol +++ b/test/Ownership.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract OwnershipTest is BaseTest { diff --git a/test/Paused.t.sol b/test/Paused.t.sol index b995049..39dab47 100644 --- a/test/Paused.t.sol +++ b/test/Paused.t.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.18; import "./BaseTest.t.sol"; -import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract PausedTest is BaseTest { @@ -37,6 +36,83 @@ contract PausedTest is BaseTest { echo.createOffer(offer); } + function testCannotCreateOfferIfCreationPaused() public { + _setCreationPaused(); + + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(CreationPaused.selector); + echo.createOffer(offer); + } + + function testCanAcceptOfferIfCreationPaused() public { + Offer memory offer = _createSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + _setCreationPaused(); + + vm.prank(account2); + echo.acceptOffer(offerId); + + // validate that the sender items are in escrow + assertOfferItemsOwnership(offer.senderItems.items, address(echo)); + // validate that the receiver items are in escrow + assertOfferItemsOwnership(offer.receiverItems.items, address(echo)); + } + + function testCanExecuteOfferIfCreationPaused() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + _setCreationPaused(); + + vm.prank(account1); + echo.executeOffer(offerId); + + // validate that the sender items are swapped + assertOfferItemsOwnership(offer.senderItems.items, offer.receiver); + // validate that the receiver items are swapped + assertOfferItemsOwnership(offer.receiverItems.items, offer.sender); + } + + function testCanRedeemExpiredOfferIfCreationPaused() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + _setCreationPaused(); + + vm.warp(in6hours); + vm.prank(account1); + echo.redeemOffer(offerId); + + vm.prank(account2); + echo.redeemOffer(offerId); + + // validate that the sender items are redeemed + assertOfferItemsOwnership(offer.senderItems.items, offer.sender); + // validate that the receiver items are redeemed + assertOfferItemsOwnership(offer.receiverItems.items, offer.receiver); + } + function testCannotAcceptOfferIfPaused() public { Offer memory offer = _createSingleAssetOffer(); bytes32 offerId = generateOfferId(offer); @@ -66,4 +142,14 @@ contract PausedTest is BaseTest { vm.expectRevert(Paused.selector); echo.executeOffer(offerId); } + + function testCannotRedeemOfferIfPaused() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + _setPaused(); + + vm.prank(account1); + vm.expectRevert(Paused.selector); + echo.redeemOffer(offerId); + } } From 97463f2daae63fd866a0daf15c3e5dc48ac13931 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 14:35:08 -0400 Subject: [PATCH 18/28] Removed dead code, added tests --- src/Echo.sol | 2 +- src/EchoState.sol | 18 +++++++------ test/CancelOffer.t.sol | 15 ++++++++++- test/CreateOffer.t.sol | 58 ++++++++++++++++++++++++++++++++++++++++++ test/Ownership.t.sol | 2 +- 5 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/Echo.sol b/src/Echo.sol index 1d5bf73..572431c 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -52,7 +52,7 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { // @dev We dont do a check on whether the offer exsits or not because // if it doesn't exist offer.sender = address(0) which can't be msg.sender if (offer.sender != msg.sender) { - revert InvalidReceiver(); + revert InvalidSender(); } // @dev Refund sender diff --git a/src/EchoState.sol b/src/EchoState.sol index 9469e47..8d5a751 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -26,10 +26,11 @@ abstract contract EchoState { } // @dev Internal function to check that offer data is valid for creation - function _validateOffer(bytes32 offerId, Offer calldata offer) internal view offerNotExpired(offer.expiration) { - if (offers[offerId].sender != address(0)) { - revert OfferAlreadyExist(); - } + function _validateOffer(Offer calldata offer) internal view offerNotExpired(offer.expiration) { + // @dev For future use... + // if (offers[offerId].sender != address(0)) { + // revert OfferAlreadyExist(); + // } if (offer.state != OfferState.OPEN) { revert InvalidOfferState(); @@ -51,7 +52,7 @@ abstract contract EchoState { function _createOffer(Offer calldata offer, uint16 chainId) internal { bytes32 offerId = _generateOfferId(offer); - _validateOffer(offerId, offer); + _validateOffer(offer); // @dev Chain must be the same as contract for same chain offers if (offer.senderItems.chainId != chainId) { @@ -68,9 +69,10 @@ abstract contract EchoState { function _acceptOffer(bytes32 offerId, Offer memory offer) internal offerNotExpired(offer.expiration) { // @dev Cannot accept an offer if it's not OPEN - if (offer.state != OfferState.OPEN) { - revert InvalidOfferState(); - } + // @dev For future use.. + // if (offer.state != OfferState.OPEN) { + // revert InvalidOfferState(); + // } offers[offerId].state = OfferState.ACCEPTED; } diff --git a/test/CancelOffer.t.sol b/test/CancelOffer.t.sol index c67012c..f53194d 100644 --- a/test/CancelOffer.t.sol +++ b/test/CancelOffer.t.sol @@ -32,7 +32,20 @@ contract CancelOfferTest is BaseTest { bytes32 offerId = generateOfferId(invalidOffer); vm.prank(account1); - vm.expectRevert(InvalidReceiver.selector); + vm.expectRevert(InvalidSender.selector); + echo.cancelOffer(offerId); + } + + function testCannotCancelAcceptedOffer() public { + Offer memory offer = _createAndAcceptSingleAssetOffer(); + bytes32 offerId = generateOfferId(offer); + + vm.prank(account1); + vm.expectRevert(InvalidOfferState.selector); + echo.cancelOffer(offerId); + + vm.prank(account2); + vm.expectRevert(InvalidSender.selector); echo.cancelOffer(offerId); } diff --git a/test/CreateOffer.t.sol b/test/CreateOffer.t.sol index b54a697..762dce2 100644 --- a/test/CreateOffer.t.sol +++ b/test/CreateOffer.t.sol @@ -36,6 +36,64 @@ contract CreateOfferTest is BaseTest { echo.createOffer(offer); } + function testCannotCreateOfferIfSenderItemsNotOnProperChain() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + 10, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(InvalidAssets.selector); + echo.createOffer(offer); + } + + function testCannotCreateOfferIfReceiverItemsNotOnProperChain() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + 10, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert(InvalidAssets.selector); + echo.createOffer(offer); + } + // TODO Not sure if this case if even possible since the assets are deposited on an offer creation // so it's impossible to recreate the same offer ID // function testCannotCreateDuplicateOffer() public { diff --git a/test/Ownership.t.sol b/test/Ownership.t.sol index a9d2156..6556b02 100644 --- a/test/Ownership.t.sol +++ b/test/Ownership.t.sol @@ -39,7 +39,7 @@ contract OwnershipTest is BaseTest { bytes32 offerId = generateOfferId(offer); vm.prank(account3); - vm.expectRevert(InvalidReceiver.selector); + vm.expectRevert(InvalidSender.selector); echo.cancelOffer(offerId); } From 0d5613095aebb734301afb53a8396a85219c02fb Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 14:41:06 -0400 Subject: [PATCH 19/28] removed dead code --- src/EchoState.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/EchoState.sol b/src/EchoState.sol index 8d5a751..546d02b 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -86,9 +86,10 @@ abstract contract EchoState { function _executeOffer(bytes32 offerId, Offer memory offer) internal offerNotExpired(offer.expiration) { // @dev Cannot execute an offer if it's not ACCEPTED - if (offer.state != OfferState.ACCEPTED) { - revert InvalidOfferState(); - } + // @dev For future use.. + // if (offer.state != OfferState.ACCEPTED) { + // revert InvalidOfferState(); + // } delete offers[offerId]; } From 200bc2e763eb14cf1ff44a03466d850a6fcc46f9 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 14:50:48 -0400 Subject: [PATCH 20/28] added more tests --- test/Approval.t.sol | 153 ++++++++++------------ test/WrongAssets.t.sol | 285 ++++++++++------------------------------- 2 files changed, 132 insertions(+), 306 deletions(-) diff --git a/test/Approval.t.sol b/test/Approval.t.sol index 3ff1b01..88ac270 100644 --- a/test/Approval.t.sol +++ b/test/Approval.t.sol @@ -6,91 +6,70 @@ import "./mock/Mocked721.sol"; import "forge-std/Test.sol"; contract ApprovalTest is BaseTest { -// Creator has not approved its apes -// function testCannotExecuteTradeIfCreatorDidNotApprove() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape3Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account3, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account3); -// vm.expectRevert(bytes("NOT_AUTHORIZED")); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -// -// /// Counterparty has not approved its birds -// function testCannotExecuteTradeIfCounterpartyDidNotApprove() public { -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// vm.startPrank(account2); -// birds.setApprovalForAll(address(echo), false); -// vm.stopPrank(); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectRevert(bytes("NOT_AUTHORIZED")); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// } -// -// /// Succeeds when both creator and counterparty have approved their assets -// function testSucceedsWhenApproved() public { -// // Assets are in original state -// assertEq(apes.ownerOf(1), account1); -// assertEq(birds.ownerOf(1), account2); -// -// creator721Collections.push(apeAddress); -// creator721Ids.push(ape1Id); -// counterparty721Collections.push(birdAddress); -// counterparty721Ids.push(bird1Id); -// -// Trade memory trade = Trade({ -// id: "test", -// creator: account1, -// counterparty: account2, -// expiresAt: in6hours, -// creatorCollections: creator721Collections, -// creatorIds: creator721Ids, -// counterpartyCollections: counterparty721Collections, -// counterpartyIds: counterparty721Ids -// }); -// -// (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = -// _prepareSignature(trade, account2PrivateKey, signerPrivateKey); -// vm.prank(account1); -// vm.expectEmit(true, true, true, true); -// emit TradeExecuted("test"); -// echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); -// -// // Assets are now swapped -// assertEq(apes.ownerOf(1), account2); -// assertEq(birds.ownerOf(1), account1); -// } + function testCannotExecuteTradeIfSenderDidNotApprove() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape3Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account3, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account3); + vm.expectRevert(bytes("NOT_AUTHORIZED")); + echo.createOffer(offer); + } + + function testCannotExecuteTradeIfReceiverDidNotApprove() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + echo.createOffer(offer); + + vm.startPrank(account2); + birds.setApprovalForAll(address(echo), false); + vm.stopPrank(); + + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + vm.expectRevert(bytes("NOT_AUTHORIZED")); + echo.acceptOffer(offerId); + } } diff --git a/test/WrongAssets.t.sol b/test/WrongAssets.t.sol index 1da1781..7af57cb 100644 --- a/test/WrongAssets.t.sol +++ b/test/WrongAssets.t.sol @@ -59,223 +59,70 @@ contract WrongAssetsTest is BaseTest { echo.createOffer(offer); } - // - // function testCannotSwapEmptyCounterpartyAssets() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert(InvalidAssets.selector); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // } - // - // function testCannotSwapEmptyAssets() public { - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert(InvalidAssets.selector); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // } - // - // function testCannotTradeLongerCreatorIds() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // creator721Ids.push(ape2Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert(LengthMismatch.selector); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // - // // Assets are not swapped - // assertEq(apes.ownerOf(1), account1); - // assertEq(apes.ownerOf(2), account1); - // assertEq(birds.ownerOf(1), account2); - // } - // - // function testCannotTradeLongerCreatorCollections() public { - // creator721Collections.push(apeAddress); - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert(LengthMismatch.selector); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // - // // Assets are not swapped - // assertEq(apes.ownerOf(1), account1); - // assertEq(birds.ownerOf(1), account2); - // } - // - // function testCannotTradeLongerCounterpartyIds() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // counterparty721Ids.push(bird2Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert(LengthMismatch.selector); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // - // // Assets are not swapped - // assertEq(apes.ownerOf(1), account1); - // assertEq(birds.ownerOf(1), account2); - // assertEq(birds.ownerOf(2), account2); - // } - // - // function testCannotTradeLongerCounterpartyCollections() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert(LengthMismatch.selector); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // - // // Assets are not swapped - // assertEq(apes.ownerOf(1), account1); - // assertEq(birds.ownerOf(1), account2); - // } - // - // function testCannotTradeSameCreatorAssets() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert("WRONG_FROM"); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // - // // Assets are not swapped - // assertEq(apes.ownerOf(1), account1); - // assertEq(birds.ownerOf(1), account2); - // } - // - // function testCannotTradeSameCounterpartyAssets() public { - // creator721Collections.push(apeAddress); - // creator721Ids.push(ape1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // counterparty721Collections.push(birdAddress); - // counterparty721Ids.push(bird1Id); - // - // Trade memory trade = Trade({ - // id: "test", - // creator: account1, - // counterparty: account2, - // expiresAt: in6hours, - // creatorCollections: creator721Collections, - // creatorIds: creator721Ids, - // counterpartyCollections: counterparty721Collections, - // counterpartyIds: counterparty721Ids - // }); - // - // (uint8 vSigner, bytes32 rSigner, bytes32 sSigner, Signature memory signature) = - // _prepareSignature(trade, account2PrivateKey, signerPrivateKey); - // vm.prank(account1); - // vm.expectRevert("WRONG_FROM"); - // echo.executeTrade(vSigner, rSigner, sSigner, signature, trade); - // - // // Assets are not swapped - // assertEq(apes.ownerOf(1), account1); - // assertEq(birds.ownerOf(1), account2); - // } + function testCannotCreateSameCreatorAssets() public { + address[] memory senderTokenAddresses = new address[](2); + senderTokenAddresses[0] = apeAddress; + senderTokenAddresses[1] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](2); + senderTokenIds[0] = ape1Id; + senderTokenIds[1] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](1); + receiverTokenAddresses[0] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](1); + receiverTokenIds[0] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + vm.expectRevert("WRONG_FROM"); + echo.createOffer(offer); + } + + function testCannotAcceptSameCounterpartyAssets() public { + address[] memory senderTokenAddresses = new address[](1); + senderTokenAddresses[0] = apeAddress; + uint256[] memory senderTokenIds = new uint256[](1); + senderTokenIds[0] = ape1Id; + + address[] memory receiverTokenAddresses = new address[](2); + receiverTokenAddresses[0] = birdAddress; + receiverTokenAddresses[1] = birdAddress; + uint256[] memory receiverTokenIds = new uint256[](2); + receiverTokenIds[0] = bird1Id; + receiverTokenIds[1] = bird1Id; + + Offer memory offer = generateOffer( + account1, + senderTokenAddresses, + senderTokenIds, + block.chainid, + account2, + receiverTokenAddresses, + receiverTokenIds, + block.chainid, + in6hours, + OfferState.OPEN + ); + + vm.prank(account1); + echo.createOffer(offer); + + bytes32 offerId = generateOfferId(offer); + + vm.prank(account2); + vm.expectRevert("WRONG_FROM"); + echo.acceptOffer(offerId); + } } From b96168b2c278791a4d5666b6ed034ac86932dece Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 14:55:02 -0400 Subject: [PATCH 21/28] slither fix --- src/Echo.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Echo.sol b/src/Echo.sol index 572431c..a1137b1 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -12,7 +12,7 @@ import "./types/Offer.sol"; contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { // @dev For future use... - uint16 private chainId; + uint16 private immutable chainId; constructor(address owner) Admin(owner) { chainId = uint16(block.chainid); From 0996a3199c817aa43bfd753f0ac65cf4d4ec16ac Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 16:40:45 -0400 Subject: [PATCH 22/28] removed potential re-entrancy issues --- src/Echo.sol | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Echo.sol b/src/Echo.sol index a1137b1..54f9356 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -26,8 +26,8 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { if (offer.sender != msg.sender) { revert InvalidSender(); } - _deposit(offer.senderItems, offer.sender); _createOffer(offer, chainId); + _deposit(offer.senderItems, offer.sender); } function acceptOffer(bytes32 offerId) external payable nonReentrant notPaused { @@ -42,8 +42,8 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { revert InvalidReceiver(); } - _deposit(offer.receiverItems, offer.receiver); _acceptOffer(offerId, offer); + _deposit(offer.receiverItems, offer.receiver); } function cancelOffer(bytes32 offerId) external nonReentrant notPaused { @@ -55,9 +55,9 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { revert InvalidSender(); } + _cancelOffer(offerId, offer); // @dev Refund sender _withdraw(offer.senderItems, offer.sender); - _cancelOffer(offerId, offer); } function executeOffer(bytes32 offerId) external payable nonReentrant notPaused { @@ -71,9 +71,9 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { if (offer.sender != msg.sender) { revert InvalidSender(); } + _executeOffer(offerId, offer); _withdraw(offer.senderItems, offer.receiver); _withdraw(offer.receiverItems, offer.sender); - _executeOffer(offerId, offer); } // @dev Function to redeem NFTs if offer expired and trade was not executed @@ -91,8 +91,6 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { // @dev If sender, we need extra checks to make sure receiver also redeemed if offer was accepted if (msg.sender == offer.sender) { - _withdraw(offer.senderItems, offer.sender); - // @dev Receiver has escrowed only if offer was accepted if (offer.state == OfferState.ACCEPTED) { OfferItem memory receiverFirstOfferItem = offer.receiverItems.items[0]; @@ -105,8 +103,8 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { } else { delete offers[offerId]; } + _withdraw(offer.senderItems, offer.sender); } else { - _withdraw(offer.receiverItems, offer.receiver); // @dev We need to check if sender has redeemed too OfferItem memory senderFirstOfferItem = offer.senderItems.items[0]; ERC721 senderFirstNft = ERC721(senderFirstOfferItem.tokenAddress); @@ -114,6 +112,7 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { if (senderFirstNft.ownerOf(senderFirstOfferItem.tokenId) != address(this)) { delete offers[offerId]; } + _withdraw(offer.receiverItems, offer.receiver); } } } From be33a37d930bda33afb170bdeb252ce481cfb396 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 18:11:28 -0400 Subject: [PATCH 23/28] added events --- src/Echo.sol | 19 ++++++++++++++++--- src/EchoError.sol | 3 +-- src/EchoState.sol | 5 ++--- test/BaseTest.t.sol | 18 ++++++++++++++++++ test/CancelOffer.t.sol | 4 ++++ test/CreateOffer.t.sol | 33 --------------------------------- test/utils/OfferUtils.sol | 1 - 7 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/Echo.sol b/src/Echo.sol index 54f9356..c6e84b1 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -11,11 +11,16 @@ import "./escrow/Escrow.sol"; import "./types/Offer.sol"; contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { + event OfferCreated(bytes32 indexed offerId); + event OfferAccepted(bytes32 indexed offerId); + event OfferCanceled(bytes32 indexed offerId); + event OfferExecuted(bytes32 indexed offerId); // @dev For future use... - uint16 private immutable chainId; + + uint16 private immutable CHAIN_ID; constructor(address owner) Admin(owner) { - chainId = uint16(block.chainid); + CHAIN_ID = uint16(block.chainid); } /** @@ -26,8 +31,10 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { if (offer.sender != msg.sender) { revert InvalidSender(); } - _createOffer(offer, chainId); + bytes32 offerId = _createOffer(offer, CHAIN_ID); _deposit(offer.senderItems, offer.sender); + + emit OfferCreated(offerId); } function acceptOffer(bytes32 offerId) external payable nonReentrant notPaused { @@ -44,6 +51,8 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { _acceptOffer(offerId, offer); _deposit(offer.receiverItems, offer.receiver); + + emit OfferAccepted(offerId); } function cancelOffer(bytes32 offerId) external nonReentrant notPaused { @@ -58,6 +67,8 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { _cancelOffer(offerId, offer); // @dev Refund sender _withdraw(offer.senderItems, offer.sender); + + emit OfferCanceled(offerId); } function executeOffer(bytes32 offerId) external payable nonReentrant notPaused { @@ -74,6 +85,8 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { _executeOffer(offerId, offer); _withdraw(offer.senderItems, offer.receiver); _withdraw(offer.receiverItems, offer.sender); + + emit OfferExecuted(offerId); } // @dev Function to redeem NFTs if offer expired and trade was not executed diff --git a/src/EchoError.sol b/src/EchoError.sol index e147355..bb5d846 100644 --- a/src/EchoError.sol +++ b/src/EchoError.sol @@ -8,8 +8,7 @@ error InvalidPayment(); error InvalidReceiver(); error InvalidSender(); error InvalidRecipient(); -error OfferAlreadyExist(); -error OfferDoesNotExist(); +//error OfferAlreadyExist(); error OfferHasExpired(); error OfferHasNotExpired(); error Paused(); diff --git a/src/EchoState.sol b/src/EchoState.sol index 546d02b..16bbf22 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -11,7 +11,6 @@ abstract contract EchoState { * Utils */ function _generateOfferId(Offer calldata offer) internal pure returns (bytes32 offerId) { - // TODO Validate this behaviour offerId = keccak256( abi.encode( offer.sender, @@ -49,8 +48,8 @@ abstract contract EchoState { * Same chain offers */ // @dev Internal function to create a same chain offer - function _createOffer(Offer calldata offer, uint16 chainId) internal { - bytes32 offerId = _generateOfferId(offer); + function _createOffer(Offer calldata offer, uint16 chainId) internal returns (bytes32 offerId) { + offerId = _generateOfferId(offer); _validateOffer(offer); diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index b8b3679..b33e2bc 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -7,6 +7,11 @@ import "./utils/OfferUtils.sol"; import "../src/Echo.sol"; abstract contract BaseTest is Test, OfferUtils { + event OfferCreated(bytes32 indexed offerId); + event OfferAccepted(bytes32 indexed offerId); + event OfferCanceled(bytes32 indexed offerId); + event OfferExecuted(bytes32 indexed offerId); + // Exclude from coverage report function test() public override {} @@ -101,7 +106,10 @@ abstract contract BaseTest is Test, OfferUtils { OfferState.OPEN ); + bytes32 offerId = generateOfferId(offer); vm.prank(account1); + vm.expectEmit(true, true, true, true, address(echo)); + emit OfferCreated(offerId); echo.createOffer(offer); vm.stopPrank(); } @@ -134,7 +142,11 @@ abstract contract BaseTest is Test, OfferUtils { OfferState.OPEN ); + bytes32 offerId = generateOfferId(offer); + vm.prank(account1); + vm.expectEmit(true, true, true, true, address(echo)); + emit OfferCreated(offerId); echo.createOffer(offer); vm.stopPrank(); } @@ -145,6 +157,8 @@ abstract contract BaseTest is Test, OfferUtils { bytes32 offerId = generateOfferId(offer); vm.prank(account2); + vm.expectEmit(true, true, true, true, address(echo)); + emit OfferAccepted(offerId); echo.acceptOffer{value: tradingFee}(offerId); vm.stopPrank(); } @@ -155,6 +169,8 @@ abstract contract BaseTest is Test, OfferUtils { bytes32 offerId = generateOfferId(offer); vm.prank(account2); + vm.expectEmit(true, true, true, true, address(echo)); + emit OfferAccepted(offerId); echo.acceptOffer{value: tradingFee}(offerId); vm.stopPrank(); } @@ -165,6 +181,8 @@ abstract contract BaseTest is Test, OfferUtils { bytes32 offerId = generateOfferId(offer); vm.prank(account1); + vm.expectEmit(true, true, true, true, address(echo)); + emit OfferExecuted(offerId); echo.executeOffer{value: tradingFee}(offerId); vm.stopPrank(); } diff --git a/test/CancelOffer.t.sol b/test/CancelOffer.t.sol index f53194d..6c3612f 100644 --- a/test/CancelOffer.t.sol +++ b/test/CancelOffer.t.sol @@ -54,6 +54,8 @@ contract CancelOfferTest is BaseTest { bytes32 offerId = generateOfferId(offer); vm.prank(account1); + vm.expectEmit(true, true, true, true, address(echo)); + emit OfferCanceled(offerId); echo.cancelOffer(offerId); (address sender,,,,,) = echo.offers(offerId); @@ -73,6 +75,8 @@ contract CancelOfferTest is BaseTest { bytes32 offerId = generateOfferId(offer); vm.prank(account1); + vm.expectEmit(true, true, true, true, address(echo)); + emit OfferCanceled(offerId); echo.cancelOffer(offerId); (address sender,,,,,) = echo.offers(offerId); diff --git a/test/CreateOffer.t.sol b/test/CreateOffer.t.sol index 762dce2..8ddf0e0 100644 --- a/test/CreateOffer.t.sol +++ b/test/CreateOffer.t.sol @@ -94,39 +94,6 @@ contract CreateOfferTest is BaseTest { echo.createOffer(offer); } - // TODO Not sure if this case if even possible since the assets are deposited on an offer creation - // so it's impossible to recreate the same offer ID - // function testCannotCreateDuplicateOffer() public { - // Offer memory firstOffer = _createMockOffer(); - // - // address[] memory senderTokenAddresses = new address[](1); - // senderTokenAddresses[0] = apeAddress; - // uint256[] memory senderTokenIds = new uint256[](1); - // senderTokenIds[0] = ape1Id; - // - // address[] memory receiverTokenAddresses = new address[](1); - // receiverTokenAddresses[0] = birdAddress; - // uint256[] memory receiverTokenIds = new uint256[](1); - // receiverTokenIds[0] = bird1Id; - // - // Offer memory secondOffer = generateOffer( - // account1, - // senderTokenAddresses, - // senderTokenIds, - // block.chainid, - // account2, - // receiverTokenAddresses, - // receiverTokenIds, - // block.chainid, - // in6hours, - // OfferState.OPEN - // ); - // - // vm.prank(account1); - // vm.expectRevert(OfferAlreadyExist.selector); - // echo.createOffer(secondOffer); - // } - function testCanCreateOfferSingleAsset() public { Offer memory offer = _createSingleAssetOffer(); diff --git a/test/utils/OfferUtils.sol b/test/utils/OfferUtils.sol index 52415b6..2b22558 100644 --- a/test/utils/OfferUtils.sol +++ b/test/utils/OfferUtils.sol @@ -17,7 +17,6 @@ abstract contract OfferUtils is Test { uint256 public in6hours; function generateOfferId(Offer memory offer) public pure returns (bytes32 offerId) { - // TODO Validate this behaviour offerId = keccak256( abi.encode( offer.sender, From 40b8292dd8b0607978571ea7258dff4b153a5ed5 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 13 May 2024 17:13:45 -0400 Subject: [PATCH 24/28] Added blast support --- lib/blast/IBlast.sol | 55 +++++++++++++++++++ lib/blast/IBlastPoints.sol | 7 +++ ...yEchoCrossChain.s.sol => DeployEcho.s.sol} | 0 src/EchoBlast.sol | 20 +++++++ 4 files changed, 82 insertions(+) create mode 100644 lib/blast/IBlast.sol create mode 100644 lib/blast/IBlastPoints.sol rename script/{DeployEchoCrossChain.s.sol => DeployEcho.s.sol} (100%) create mode 100644 src/EchoBlast.sol diff --git a/lib/blast/IBlast.sol b/lib/blast/IBlast.sol new file mode 100644 index 0000000..e3eefd2 --- /dev/null +++ b/lib/blast/IBlast.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +enum YieldMode { + AUTOMATIC, + VOID, + CLAIMABLE +} + +enum GasMode { + VOID, + CLAIMABLE +} + +interface IBlast { + // configure + function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external; + function configure(YieldMode _yield, GasMode gasMode, address governor) external; + + // base configuration options + function configureClaimableYield() external; + function configureClaimableYieldOnBehalf(address contractAddress) external; + function configureAutomaticYield() external; + function configureAutomaticYieldOnBehalf(address contractAddress) external; + function configureVoidYield() external; + function configureVoidYieldOnBehalf(address contractAddress) external; + function configureClaimableGas() external; + function configureClaimableGasOnBehalf(address contractAddress) external; + function configureVoidGas() external; + function configureVoidGasOnBehalf(address contractAddress) external; + function configureGovernor(address _governor) external; + function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external; + + // claim yield + function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256); + function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256); + + // claim gas + function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256); + function claimGasAtMinClaimRate(address contractAddress, address recipientOfGas, uint256 minClaimRateBips) + external + returns (uint256); + function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256); + function claimGas(address contractAddress, address recipientOfGas, uint256 gasToClaim, uint256 gasSecondsToConsume) + external + returns (uint256); + + // read functions + function readClaimableYield(address contractAddress) external view returns (uint256); + function readYieldConfiguration(address contractAddress) external view returns (uint8); + function readGasParams(address contractAddress) + external + view + returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode); +} diff --git a/lib/blast/IBlastPoints.sol b/lib/blast/IBlastPoints.sol new file mode 100644 index 0000000..f570614 --- /dev/null +++ b/lib/blast/IBlastPoints.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +interface IBlastPoints { + function configurePointsOperator(address operator) external; + function configurePointsOperatorOnBehalf(address contractAddress, address operator) external; +} diff --git a/script/DeployEchoCrossChain.s.sol b/script/DeployEcho.s.sol similarity index 100% rename from script/DeployEchoCrossChain.s.sol rename to script/DeployEcho.s.sol diff --git a/src/EchoBlast.sol b/src/EchoBlast.sol new file mode 100644 index 0000000..c5493a6 --- /dev/null +++ b/src/EchoBlast.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import "./Echo.sol"; +import "blast/IBlast.sol"; +import "blast/IBlastPoints.sol"; + +contract EchoBlast is Echo { + IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002); + + constructor(address owner, address blastPointsAddress) Echo(owner) { + IBlastPoints(blastPointsAddress).configurePointsOperator(owner); + BLAST.configureAutomaticYield(); + BLAST.configureClaimableGas(); + } + + function claimGas() external onlyOwner { + BLAST.claimMaxGas(address(this), msg.sender); + } +} From 9eeb04ce808d28e8bbcf232a5a5eac10b494baca Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Tue, 14 May 2024 16:30:34 -0400 Subject: [PATCH 25/28] updated scripts --- .env.example | 2 +- foundry.toml | 7 +++++++ script/DeployEcho.s.sol | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 59a8454..66ef206 100644 --- a/.env.example +++ b/.env.example @@ -2,4 +2,4 @@ MAINNET_RPC_URL= SEPOLIA_RPC_URL= PRIVATE_KEY= MAINNET_PRIVATE_KEY= -ETHERSCAN_KEY= \ No newline at end of file +ETHERSCAN_API_KEY= \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index e35a001..4c4279b 100644 --- a/foundry.toml +++ b/foundry.toml @@ -17,3 +17,10 @@ fuzz_runs = 1000 verbosity = 4 gas_reports = ["Echo"] + +# Config +[rpc_endpoints] +sepolia = "${SEPOLIA_RPC_URL}" + +[etherscan] +sepolia = { key = "${ETHERSCAN_API_KEY}" } \ No newline at end of file diff --git a/script/DeployEcho.s.sol b/script/DeployEcho.s.sol index f13a394..d918c16 100644 --- a/script/DeployEcho.s.sol +++ b/script/DeployEcho.s.sol @@ -9,7 +9,8 @@ contract DeployEcho is Script { function test() public {} function run() external { - vm.startBroadcast(); + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); new Echo({owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09)}); vm.stopBroadcast(); From 71aa844bf3796712fe9015f1eaf947ea378fe67d Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 27 May 2024 14:32:19 -0400 Subject: [PATCH 26/28] Small update Publishing on blast now works Added a few more scripts Fixed the chain id bug --- foundry.toml | 4 +- script/DeployERC721.s.sol | 73 +++++++++++++++++++++++++++++++++--- script/DeployEchoBlast.s.sol | 28 ++++++++++++++ script/TestPacking.s.sol | 38 +++++++++++++++++++ script/UpdateEchoFees.s.sol | 18 +++++++++ src/Echo.sol | 6 +-- src/EchoBlast.sol | 4 +- src/EchoState.sol | 2 +- test/mock/YieldMock.sol | 23 ++++++++++++ 9 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 script/DeployEchoBlast.s.sol create mode 100644 script/TestPacking.s.sol create mode 100644 script/UpdateEchoFees.s.sol create mode 100644 test/mock/YieldMock.sol diff --git a/foundry.toml b/foundry.toml index 4c4279b..6db4fea 100644 --- a/foundry.toml +++ b/foundry.toml @@ -21,6 +21,8 @@ gas_reports = ["Echo"] # Config [rpc_endpoints] sepolia = "${SEPOLIA_RPC_URL}" +blast_sepolia = "${BLAST_SEPOLIA_RPC_URL}" [etherscan] -sepolia = { key = "${ETHERSCAN_API_KEY}" } \ No newline at end of file +sepolia = { key = "${ETHERSCAN_API_KEY}" } +blast_sepolia = { key = "${BLASTSCAN_API_KEY}", url="https://api-sepolia.blastscan.io/api" } \ No newline at end of file diff --git a/script/DeployERC721.s.sol b/script/DeployERC721.s.sol index dbddde6..7b596a3 100644 --- a/script/DeployERC721.s.sol +++ b/script/DeployERC721.s.sol @@ -9,13 +9,76 @@ contract DeployNFT is Script { function test() public {} function run() external { - vm.startBroadcast(); + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); - Mocked721 YKPS = new Mocked721({name: "Kanpai Panda", symbol: "YKPS"}); - YKPS.setBaseURI("https://prod.kanpaidev.com/api/token/"); + address gab = address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09); + address jf = address(0x1E3918dD44F427F056be6C8E132cF1b5F42de59E); - Mocked721WithSuffix MAD = new Mocked721WithSuffix({name: "Mad Lads", symbol: "MAD"}); - MAD.setBaseURI("https://madlads.s3.us-west-2.amazonaws.com/json/"); + Mocked721WithSuffix CBC = new Mocked721WithSuffix({name: "Creepz by OVERLORD", symbol: "CBC"}); + CBC.setBaseURI("ipfs://QmVRsXpYYp3qALoxjYUfNZAA6A28P86REKkoqadoXM5tLn/"); + + Mocked721 BAYC = new Mocked721({name: "BoredApeYachtClub", symbol: "BAYC"}); + BAYC.setBaseURI("ipfs://QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/"); + + Mocked721 SORA = new Mocked721({name: "Sora's Dreamworld", symbol: "Sora"}); + SORA.setBaseURI("https://sorasdreamworld.io/tokens/"); + + Mocked721 MAYC = new Mocked721({name: "MutantApeYachtClub", symbol: "MAYC"}); + MAYC.setBaseURI("https://boredapeyachtclub.com/api/mutants/"); + + // Mint NFTs + //CBC + CBC.safeMint(gab, 0); + CBC.safeMint(gab, 1); + CBC.safeMint(gab, 2); + CBC.safeMint(gab, 3); + CBC.safeMint(gab, 4); + + CBC.safeMint(jf, 5); + CBC.safeMint(jf, 6); + CBC.safeMint(jf, 7); + CBC.safeMint(jf, 8); + CBC.safeMint(jf, 9); + + // BAYC + BAYC.safeMint(gab, 0); + BAYC.safeMint(gab, 1); + BAYC.safeMint(gab, 2); + BAYC.safeMint(gab, 3); + BAYC.safeMint(gab, 4); + + BAYC.safeMint(jf, 5); + BAYC.safeMint(jf, 6); + BAYC.safeMint(jf, 7); + BAYC.safeMint(jf, 8); + BAYC.safeMint(jf, 9); + + // SORA + SORA.safeMint(gab, 0); + SORA.safeMint(gab, 1); + SORA.safeMint(gab, 2); + SORA.safeMint(gab, 3); + SORA.safeMint(gab, 4); + + SORA.safeMint(jf, 5); + SORA.safeMint(jf, 6); + SORA.safeMint(jf, 7); + SORA.safeMint(jf, 8); + SORA.safeMint(jf, 9); + + // MAYC + MAYC.safeMint(gab, 0); + MAYC.safeMint(gab, 1); + MAYC.safeMint(gab, 2); + MAYC.safeMint(gab, 3); + MAYC.safeMint(gab, 4); + + MAYC.safeMint(jf, 5); + MAYC.safeMint(jf, 6); + MAYC.safeMint(jf, 7); + MAYC.safeMint(jf, 8); + MAYC.safeMint(jf, 9); vm.stopBroadcast(); } diff --git a/script/DeployEchoBlast.s.sol b/script/DeployEchoBlast.s.sol new file mode 100644 index 0000000..3558b3f --- /dev/null +++ b/script/DeployEchoBlast.s.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Script.sol"; +import "../src/EchoBlast.sol"; +import "../test/mock/YieldMock.sol"; + +contract DeployEchoBlast is Script { + // Exclude from coverage report + function test() public {} + + function run() external { + vm.createSelectFork(vm.envString("BLAST_SEPOLIA_RPC_URL")); + // Deploy mock of the precompile + YieldMock yieldMock = new YieldMock(); + // Set mock bytecode to the expected precompile address + vm.etch(0x0000000000000000000000000000000000000100, address(yieldMock).code); + + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + new EchoBlast({ + owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), + blastPointsAddress: address(0x2fc95838c71e76ec69ff817983BFf17c710F34E0) + }); + + vm.stopBroadcast(); + } +} diff --git a/script/TestPacking.s.sol b/script/TestPacking.s.sol new file mode 100644 index 0000000..6d75667 --- /dev/null +++ b/script/TestPacking.s.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Script.sol"; +import "../src/Echo.sol"; + +contract TestPacking is Script { + // Exclude from coverage report + function test() public {} + + function run() external { + OfferItem[] memory offerItems = new OfferItem[](1); + offerItems[0] = OfferItem({tokenAddress: 0x7DA16cd402106Adaf39092215DbB54092b80B6E6, tokenId: 2}); + + Offer memory offer = Offer({ + sender: 0x7DA16cd402106Adaf39092215DbB54092b80B6E6, + receiver: 0x7DA16cd402106Adaf39092215DbB54092b80B6E6, + senderItems: OfferItems({chainId: 1, items: offerItems}), + receiverItems: OfferItems({chainId: 1, items: offerItems}), + expiration: 1, + state: OfferState.OPEN + }); + + bytes memory offerIdHash = abi.encode( + offer.sender, + offer.receiver, + offer.senderItems.chainId, + keccak256(abi.encode(offer.senderItems.items)), // OfferItem[] + offer.receiverItems.chainId, + keccak256(abi.encode(offer.receiverItems.items)), // OfferItem[] + offer.expiration + ); + bytes32 offerId = keccak256(offerIdHash); + + console.logBytes(offerIdHash); + console.logBytes32(offerId); + } +} diff --git a/script/UpdateEchoFees.s.sol b/script/UpdateEchoFees.s.sol new file mode 100644 index 0000000..b2b2fae --- /dev/null +++ b/script/UpdateEchoFees.s.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Script.sol"; +import "../src/Echo.sol"; + +contract UpdateEchoFees is Script { + // Exclude from coverage report + function test() public {} + + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + Echo echo = Echo(0xB0904D81440EFCA27Ec61948c95f21D7d546F8C3); + echo.setFees(0.005 ether); + vm.stopBroadcast(); + } +} diff --git a/src/Echo.sol b/src/Echo.sol index c6e84b1..9d9d7b3 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -15,12 +15,12 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { event OfferAccepted(bytes32 indexed offerId); event OfferCanceled(bytes32 indexed offerId); event OfferExecuted(bytes32 indexed offerId); - // @dev For future use... - uint16 private immutable CHAIN_ID; + // @dev For future use... + uint256 private immutable CHAIN_ID; constructor(address owner) Admin(owner) { - CHAIN_ID = uint16(block.chainid); + CHAIN_ID = block.chainid; } /** diff --git a/src/EchoBlast.sol b/src/EchoBlast.sol index c5493a6..1664e8f 100644 --- a/src/EchoBlast.sol +++ b/src/EchoBlast.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.18; import "./Echo.sol"; -import "blast/IBlast.sol"; -import "blast/IBlastPoints.sol"; +import "../lib/blast/IBlast.sol"; +import "../lib/blast/IBlastPoints.sol"; contract EchoBlast is Echo { IBlast public constant BLAST = IBlast(0x4300000000000000000000000000000000000002); diff --git a/src/EchoState.sol b/src/EchoState.sol index 16bbf22..86a8bb0 100644 --- a/src/EchoState.sol +++ b/src/EchoState.sol @@ -48,7 +48,7 @@ abstract contract EchoState { * Same chain offers */ // @dev Internal function to create a same chain offer - function _createOffer(Offer calldata offer, uint16 chainId) internal returns (bytes32 offerId) { + function _createOffer(Offer calldata offer, uint256 chainId) internal returns (bytes32 offerId) { offerId = _generateOfferId(offer); _validateOffer(offer); diff --git a/test/mock/YieldMock.sol b/test/mock/YieldMock.sol new file mode 100644 index 0000000..d63a17d --- /dev/null +++ b/test/mock/YieldMock.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +contract YieldMock { + address private constant blastContract = 0x4300000000000000000000000000000000000002; + + mapping(address => uint8) public getConfiguration; + + function configure(address contractAddress, uint8 flags) external returns (uint256) { + require(msg.sender == blastContract); + + getConfiguration[contractAddress] = flags; + return 0; + } + + function claim(address, address, uint256) external pure returns (uint256) { + return 0; + } + + function getClaimableAmount(address) external pure returns (uint256) { + return 0; + } +} From 927db1afdf75e6a49881dc6227a7f16e4282f5ee Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Mon, 27 May 2024 18:23:51 -0400 Subject: [PATCH 27/28] Added OfferRedeemed event --- src/Echo.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Echo.sol b/src/Echo.sol index 9d9d7b3..e7f8469 100644 --- a/src/Echo.sol +++ b/src/Echo.sol @@ -15,6 +15,7 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { event OfferAccepted(bytes32 indexed offerId); event OfferCanceled(bytes32 indexed offerId); event OfferExecuted(bytes32 indexed offerId); + event OfferRedeeemed(bytes32 indexed offerId, address indexed owner); // @dev For future use... uint256 private immutable CHAIN_ID; @@ -127,5 +128,6 @@ contract Echo is ReentrancyGuard, Admin, Banker, Escrow, EchoState { } _withdraw(offer.receiverItems, offer.receiver); } + emit OfferRedeeemed(offerId, msg.sender); } } From 9f076f30b01ada79b1e1f24f1f411189d9af0b20 Mon Sep 17 00:00:00 2001 From: Gabriel Cartier <4060669+GabrielCartier@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:39:08 -0400 Subject: [PATCH 28/28] fixed scripts --- foundry.toml | 4 +- pnpm-lock.yaml | 3418 +++++++++++++++------------ script/DeployEchoBlast.s.sol | 6 +- script/DeployEchoBlastMainnet.s.sol | 26 + script/MintNfts.s.sol | 64 +- script/TransferNfts.s.sol | 26 + script/UpdateEchoFees.s.sol | 6 +- 7 files changed, 1999 insertions(+), 1551 deletions(-) create mode 100644 script/DeployEchoBlastMainnet.s.sol create mode 100644 script/TransferNfts.s.sol diff --git a/foundry.toml b/foundry.toml index 6db4fea..b12a860 100644 --- a/foundry.toml +++ b/foundry.toml @@ -22,7 +22,9 @@ gas_reports = ["Echo"] [rpc_endpoints] sepolia = "${SEPOLIA_RPC_URL}" blast_sepolia = "${BLAST_SEPOLIA_RPC_URL}" +blast = "${BLAST_RPC_URL}" [etherscan] sepolia = { key = "${ETHERSCAN_API_KEY}" } -blast_sepolia = { key = "${BLASTSCAN_API_KEY}", url="https://api-sepolia.blastscan.io/api" } \ No newline at end of file +blast_sepolia = { key = "${BLASTSCAN_API_KEY}", url="https://api-sepolia.blastscan.io/api" } +blast = { key = "${BLASTSCAN_API_KEY}", url="https://api.blastscan.io/api" } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0cab832..d8857e6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,118 +1,1573 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -devDependencies: - husky: - specifier: 9.0.11 - version: 9.0.11 - lint-staged: - specifier: 15.2.2 - version: 15.2.2 - npm-check-updates: - specifier: 16.14.20 - version: 16.14.20 - prettier: - specifier: 3.2.5 - version: 3.2.5 - prettier-plugin-solidity: - specifier: 1.3.1 - version: 1.3.1(prettier@3.2.5) - solhint: - specifier: 4.5.4 - version: 4.5.4 - solhint-plugin-prettier: - specifier: 0.1.0 - version: 0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5) +importers: + + .: + devDependencies: + husky: + specifier: 9.0.11 + version: 9.0.11 + lint-staged: + specifier: 15.2.2 + version: 15.2.2 + npm-check-updates: + specifier: 16.14.20 + version: 16.14.20 + prettier: + specifier: 3.2.5 + version: 3.2.5 + prettier-plugin-solidity: + specifier: 1.3.1 + version: 1.3.1(prettier@3.2.5) + solhint: + specifier: 4.5.4 + version: 4.5.4 + solhint-plugin-prettier: + specifier: 0.1.0 + version: 0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5) packages: - /@babel/code-frame@7.23.5: + '@babel/code-frame@7.23.5': resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.22.20': + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.23.4': + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + + '@colors/colors@1.5.0': + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + + '@gar/promisify@1.1.3': + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@npmcli/fs@2.1.2': + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + '@npmcli/fs@3.1.1': + resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/git@4.1.0': + resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/installed-package-contents@2.1.0': + resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + '@npmcli/move-file@2.0.1': + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + + '@npmcli/node-gyp@3.0.0': + resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/promise-spawn@6.0.2': + resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@npmcli/run-script@6.0.2': + resolution: {integrity: sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pnpm/config.env-replace@1.1.0': + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + + '@pnpm/network.ca-file@1.0.2': + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + + '@pnpm/npm-conf@2.2.2': + resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} + engines: {node: '>=12'} + + '@prettier/sync@0.3.0': + resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} + peerDependencies: + prettier: ^3.0.0 + + '@sigstore/bundle@1.1.0': + resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@sigstore/protobuf-specs@0.2.1': + resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@sigstore/sign@1.0.0': + resolution: {integrity: sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@sigstore/tuf@1.0.3': + resolution: {integrity: sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@sindresorhus/is@5.6.0': + resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} + engines: {node: '>=14.16'} + + '@solidity-parser/parser@0.17.0': + resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} + + '@solidity-parser/parser@0.18.0': + resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} + + '@szmarczak/http-timer@5.0.1': + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} + + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + + '@tufjs/canonical-json@1.0.0': + resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@tufjs/models@1.0.4': + resolution: {integrity: sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + '@types/http-cache-semantics@4.0.4': + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + + '@types/semver-utils@1.1.3': + resolution: {integrity: sha512-T+YwkslhsM+CeuhYUxyAjWm7mJ5am/K10UX40RuA6k6Lc7eGtq8iY2xOzy7Vq0GOqhl/xZl5l2FwURZMTPTUww==} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-escapes@6.2.0: + resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} + engines: {node: '>=14.16'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + antlr4@4.13.1: + resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} + engines: {node: '>=16'} + + aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + + are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + ast-parents@0.0.1: + resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + boxen@7.1.1: + resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} + engines: {node: '>=14.16'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + cacache@17.1.4: + resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + + cacheable-request@10.2.14: + resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} + engines: {node: '>=14.16'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + cli-table3@0.6.4: + resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + engines: {node: 10.* || >= 12.*} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + configstore@6.0.0: + resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} + engines: {node: '>=12'} + + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + crypto-random-string@4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dot-prop@6.0.1: + resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} + engines: {node: '>=10'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + escape-goat@4.0.0: + resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} + engines: {node: '>=12'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + exponential-backoff@3.1.1: + resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-memoize@2.5.2: + resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + + form-data-encoder@2.1.4: + resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} + engines: {node: '>= 14.17'} + + fp-and-or@0.1.4: + resolution: {integrity: sha512-+yRYRhpnFPWXSly/6V4Lw9IfOV26uu30kynGJ03PW+MnjOEQe45RZ141QcS0aJehYBYA50GfCDnsRbFJdhssRw==} + engines: {node: '>=10'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs-minipass@3.0.3: + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + + get-stdin@8.0.0: + resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} + engines: {node: '>=10'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@10.3.14: + resolution: {integrity: sha512-4fkAqu93xe9Mk7le9v0y3VrPDqLKHarNi2s4Pv7f2yOvfhWfhc7hRPHC/JyqMqb8B/Dt/eGS4n7ykwf3fOsl8g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + + global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + got@12.6.1: + resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} + engines: {node: '>=14.16'} + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + has-yarn@3.0.0: + resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hosted-git-info@5.2.1: + resolution: {integrity: sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + hosted-git-info@6.1.1: + resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + husky@9.0.11: + resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} + engines: {node: '>=18'} + hasBin: true + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore-walk@6.0.5: + resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + + ini@4.1.2: + resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true + + is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-installed-globally@0.4.0: + resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} + engines: {node: '>=10'} + + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + + is-npm@6.0.0: + resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + is-yarn-global@0.4.1: + resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} + engines: {node: '>=12'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-parse-even-better-errors@3.0.2: + resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + json-parse-helpfulerror@1.0.3: + resolution: {integrity: sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonlines@0.1.1: + resolution: {integrity: sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==} + + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + latest-version@7.0.0: + resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} + engines: {node: '>=14.16'} + + lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + lint-staged@15.2.2: + resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.0.1: + resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} + engines: {node: '>=18.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} + + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + make-fetch-happen@11.1.1: + resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + + minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + minipass-fetch@3.0.5: + resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + + minipass-json-stream@1.0.1: + resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.1.1: + resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + node-gyp@9.4.1: + resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} + engines: {node: ^12.13 || ^14.13 || >=16} + hasBin: true + + nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + + normalize-package-data@5.0.0: + resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + normalize-url@8.0.0: + resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} + engines: {node: '>=14.16'} + + npm-bundled@3.0.1: + resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-check-updates@16.14.20: + resolution: {integrity: sha512-sYbIhun4DrjO7NFOTdvs11nCar0etEhZTsEjL47eM0TuiGMhmYughRCxG2SpGRmGAQ7AkwN7bw2lWzoE7q6yOQ==} + engines: {node: '>=14.14'} + hasBin: true + + npm-install-checks@6.3.0: + resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-normalize-package-bin@3.0.1: + resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-package-arg@10.1.0: + resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-packlist@7.0.4: + resolution: {integrity: sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-pick-manifest@8.0.2: + resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-registry-fetch@14.0.5: + resolution: {integrity: sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + package-json@8.1.1: + resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} + engines: {node: '>=14.16'} + + pacote@15.2.0: + resolution: {integrity: sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-github-url@1.0.2: + resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==} + engines: {node: '>=0.10.0'} + hasBin: true + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-scurry@1.11.0: + resolution: {integrity: sha512-LNHTaVkzaYaLGlO+0u3rQTz7QrHTFOuKyba9JMTQutkmtNew8dw8wOD7mTU/5fCPZzCWpfW0XnQKzY61P0aTaw==} + engines: {node: '>=16 || 14 >=14.17'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier-plugin-solidity@1.3.1: + resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} + engines: {node: '>=16'} + peerDependencies: + prettier: '>=2.3.0' + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + + proc-log@3.0.0: + resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + prompts-ncu@3.0.0: + resolution: {integrity: sha512-qyz9UxZ5MlPKWVhWrCmSZ1ahm2GVYdjLb8og2sg0IPth1KRuhcggHGuijz0e41dkx35p1t1q3GRISGH7QGALFA==} + engines: {node: '>= 14'} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pupa@3.1.0: + resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} + engines: {node: '>=12.20'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + rc-config-loader@4.1.3: + resolution: {integrity: sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + read-package-json-fast@3.0.2: + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + read-package-json@6.0.4: + resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + registry-auth-token@5.0.2: + resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} + engines: {node: '>=14'} + + registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} + + remote-git-tags@3.0.0: + resolution: {integrity: sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==} + engines: {node: '>=8'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} + + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.3.1: + resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + + rimraf@5.0.6: + resolution: {integrity: sha512-X72SgyOf+1lFnGM6gYcmZ4+jMOwuT4E4SajKQzUIlI7EoR5eFHMhS/wf8Ll0mN+w2bxcIVldrJQ6xT7HFQywjg==} + engines: {node: '>=14'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver-diff@4.0.0: + resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} + engines: {node: '>=12'} + + semver-utils@1.1.4: + resolution: {integrity: sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==} + + semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sigstore@1.9.0: + resolution: {integrity: sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + + socks@2.8.3: + resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + solhint-plugin-prettier@0.1.0: + resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-solidity: ^1.0.0 + + solhint@4.5.4: + resolution: {integrity: sha512-Cu1XiJXub2q1eCr9kkJ9VPv1sGcmj3V7Zb76B0CoezDOB9bu3DxKIFFH7ggCl9fWpEPD6xBmRLfZrYijkVmujQ==} + hasBin: true + + solidity-comments-extractor@0.0.8: + resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spawn-please@2.0.2: + resolution: {integrity: sha512-KM8coezO6ISQ89c1BzyWNtcn2V2kAVtwIXd3cN/V5a0xPYc1F/vydrRc01wsKFEQ/p+V1a4sw4z2yMITIXrgGw==} + engines: {node: '>=14'} + + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.17: + resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + ssri@10.0.6: + resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.1.0: + resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} + engines: {node: '>=18'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@5.0.1: + resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} + engines: {node: '>=14.16'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + table@6.8.1: + resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} + engines: {node: '>=10.0.0'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tuf-js@1.1.7: + resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + + typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + + unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + unique-filename@3.0.0: + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + unique-slug@4.0.0: + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + unique-string@3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} + + untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + + update-notifier@6.0.2: + resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} + engines: {node: '>=14.16'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@3.0.1: + resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + + xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@babel/code-frame@7.23.5': dependencies: '@babel/highlight': 7.23.4 chalk: 2.4.2 - dev: true - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-validator-identifier@7.22.20': {} - /@babel/highlight@7.23.4: - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} - engines: {node: '>=6.9.0'} + '@babel/highlight@7.23.4': dependencies: '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 - dev: true - /@colors/colors@1.5.0: - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} - requiresBuild: true - dev: true + '@colors/colors@1.5.0': optional: true - /@gar/promisify@1.1.3: - resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - dev: true + '@gar/promisify@1.1.3': {} - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 + string-width-cjs: string-width@4.2.3 strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 + strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true + wrap-ansi-cjs: wrap-ansi@7.0.0 - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: true - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true + '@nodelib/fs.stat@2.0.5': {} - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - dev: true - /@npmcli/fs@2.1.2: - resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + '@npmcli/fs@2.1.2': dependencies: '@gar/promisify': 1.1.3 semver: 7.6.0 - dev: true - /@npmcli/fs@3.1.1: - resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@npmcli/fs@3.1.1': dependencies: semver: 7.6.0 - dev: true - /@npmcli/git@4.1.0: - resolution: {integrity: sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@npmcli/git@4.1.0': dependencies: '@npmcli/promise-spawn': 6.0.2 lru-cache: 7.18.3 @@ -124,41 +1579,24 @@ packages: which: 3.0.1 transitivePeerDependencies: - bluebird - dev: true - /@npmcli/installed-package-contents@2.1.0: - resolution: {integrity: sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true + '@npmcli/installed-package-contents@2.1.0': dependencies: npm-bundled: 3.0.1 npm-normalize-package-bin: 3.0.1 - dev: true - /@npmcli/move-file@2.0.1: - resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This functionality has been moved to @npmcli/fs + '@npmcli/move-file@2.0.1': dependencies: mkdirp: 1.0.4 rimraf: 3.0.2 - dev: true - /@npmcli/node-gyp@3.0.0: - resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true + '@npmcli/node-gyp@3.0.0': {} - /@npmcli/promise-spawn@6.0.2: - resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@npmcli/promise-spawn@6.0.2': dependencies: which: 3.0.1 - dev: true - /@npmcli/run-script@6.0.2: - resolution: {integrity: sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@npmcli/run-script@6.0.2': dependencies: '@npmcli/node-gyp': 3.0.0 '@npmcli/promise-spawn': 6.0.2 @@ -168,253 +1606,143 @@ packages: transitivePeerDependencies: - bluebird - supports-color - dev: true - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true + '@pkgjs/parseargs@0.11.0': optional: true - /@pnpm/config.env-replace@1.1.0: - resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} - engines: {node: '>=12.22.0'} - dev: true + '@pnpm/config.env-replace@1.1.0': {} - /@pnpm/network.ca-file@1.0.2: - resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} - engines: {node: '>=12.22.0'} + '@pnpm/network.ca-file@1.0.2': dependencies: graceful-fs: 4.2.10 - dev: true - /@pnpm/npm-conf@2.2.2: - resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} - engines: {node: '>=12'} + '@pnpm/npm-conf@2.2.2': dependencies: '@pnpm/config.env-replace': 1.1.0 '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - dev: true - /@prettier/sync@0.3.0(prettier@3.2.5): - resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==} - peerDependencies: - prettier: ^3.0.0 + '@prettier/sync@0.3.0(prettier@3.2.5)': dependencies: prettier: 3.2.5 - dev: true - /@sigstore/bundle@1.1.0: - resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@sigstore/bundle@1.1.0': dependencies: '@sigstore/protobuf-specs': 0.2.1 - dev: true - /@sigstore/protobuf-specs@0.2.1: - resolution: {integrity: sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true + '@sigstore/protobuf-specs@0.2.1': {} - /@sigstore/sign@1.0.0: - resolution: {integrity: sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@sigstore/sign@1.0.0': dependencies: '@sigstore/bundle': 1.1.0 '@sigstore/protobuf-specs': 0.2.1 make-fetch-happen: 11.1.1 transitivePeerDependencies: - supports-color - dev: true - /@sigstore/tuf@1.0.3: - resolution: {integrity: sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@sigstore/tuf@1.0.3': dependencies: '@sigstore/protobuf-specs': 0.2.1 tuf-js: 1.1.7 transitivePeerDependencies: - supports-color - dev: true - /@sindresorhus/is@5.6.0: - resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} - engines: {node: '>=14.16'} - dev: true + '@sindresorhus/is@5.6.0': {} - /@solidity-parser/parser@0.17.0: - resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} - dev: true + '@solidity-parser/parser@0.17.0': {} - /@solidity-parser/parser@0.18.0: - resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} - dev: true + '@solidity-parser/parser@0.18.0': {} - /@szmarczak/http-timer@5.0.1: - resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} - engines: {node: '>=14.16'} + '@szmarczak/http-timer@5.0.1': dependencies: defer-to-connect: 2.0.1 - dev: true - /@tootallnate/once@2.0.0: - resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} - engines: {node: '>= 10'} - dev: true + '@tootallnate/once@2.0.0': {} - /@tufjs/canonical-json@1.0.0: - resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true + '@tufjs/canonical-json@1.0.0': {} - /@tufjs/models@1.0.4: - resolution: {integrity: sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@tufjs/models@1.0.4': dependencies: '@tufjs/canonical-json': 1.0.0 minimatch: 9.0.4 - dev: true - /@types/http-cache-semantics@4.0.4: - resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} - dev: true + '@types/http-cache-semantics@4.0.4': {} - /@types/semver-utils@1.1.3: - resolution: {integrity: sha512-T+YwkslhsM+CeuhYUxyAjWm7mJ5am/K10UX40RuA6k6Lc7eGtq8iY2xOzy7Vq0GOqhl/xZl5l2FwURZMTPTUww==} - dev: true + '@types/semver-utils@1.1.3': {} - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true + abbrev@1.1.1: {} - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} + agent-base@6.0.2: dependencies: debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true - /agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} - engines: {node: '>= 8.0.0'} + agentkeepalive@4.5.0: dependencies: humanize-ms: 1.2.1 - dev: true - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 - dev: true - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: true - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + ajv@8.12.0: dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 uri-js: 4.4.1 - dev: true - /ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + ansi-align@3.0.1: dependencies: string-width: 4.2.3 - dev: true - /ansi-escapes@6.2.0: - resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} - engines: {node: '>=14.16'} + ansi-escapes@6.2.0: dependencies: type-fest: 3.13.1 - dev: true - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true + ansi-regex@5.0.1: {} - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true + ansi-regex@6.0.1: {} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 - dev: true - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - dev: true - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true + ansi-styles@6.2.1: {} - /antlr4@4.13.1: - resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} - engines: {node: '>=16'} - dev: true + antlr4@4.13.1: {} - /aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: true + aproba@2.0.0: {} - /are-we-there-yet@3.0.1: - resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + are-we-there-yet@3.0.1: dependencies: delegates: 1.0.0 readable-stream: 3.6.2 - dev: true - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true + argparse@2.0.1: {} - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true + array-union@2.1.0: {} - /ast-parents@0.0.1: - resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} - dev: true + ast-parents@0.0.1: {} - /astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true + astral-regex@2.0.0: {} - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true + balanced-match@1.0.2: {} - /boxen@7.1.1: - resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} - engines: {node: '>=14.16'} + boxen@7.1.1: dependencies: ansi-align: 3.0.1 camelcase: 7.0.1 @@ -424,35 +1752,23 @@ packages: type-fest: 2.19.0 widest-line: 4.0.1 wrap-ansi: 8.1.0 - dev: true - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.0.1 - dev: true - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true + buffer-from@1.1.2: {} - /cacache@16.1.3: - resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + cacache@16.1.3: dependencies: '@npmcli/fs': 2.1.2 '@npmcli/move-file': 2.0.1 @@ -474,11 +1790,8 @@ packages: unique-filename: 2.0.1 transitivePeerDependencies: - bluebird - dev: true - /cacache@17.1.4: - resolution: {integrity: sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + cacache@17.1.4: dependencies: '@npmcli/fs': 3.1.1 fs-minipass: 3.0.3 @@ -492,16 +1805,10 @@ packages: ssri: 10.0.6 tar: 6.2.1 unique-filename: 3.0.0 - dev: true - /cacheable-lookup@7.0.0: - resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} - engines: {node: '>=14.16'} - dev: true + cacheable-lookup@7.0.0: {} - /cacheable-request@10.2.14: - resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} - engines: {node: '>=14.16'} + cacheable-request@10.2.14: dependencies: '@types/http-cache-semantics': 4.0.4 get-stream: 6.0.1 @@ -510,284 +1817,151 @@ packages: mimic-response: 4.0.0 normalize-url: 8.0.0 responselike: 3.0.0 - dev: true - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true + callsites@3.1.0: {} - /camelcase@7.0.1: - resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} - engines: {node: '>=14.16'} - dev: true + camelcase@7.0.1: {} - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 escape-string-regexp: 1.0.5 supports-color: 5.5.0 - dev: true - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true + chalk@5.3.0: {} - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - dev: true + chownr@2.0.0: {} - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true + ci-info@3.9.0: {} - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - dev: true + clean-stack@2.2.0: {} - /cli-boxes@3.0.0: - resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} - engines: {node: '>=10'} - dev: true + cli-boxes@3.0.0: {} - /cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-cursor@4.0.0: dependencies: restore-cursor: 4.0.0 - dev: true - /cli-table3@0.6.4: - resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} - engines: {node: 10.* || >= 12.*} + cli-table3@0.6.4: dependencies: string-width: 4.2.3 optionalDependencies: '@colors/colors': 1.5.0 - dev: true - /cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} + cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 string-width: 7.1.0 - dev: true - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@1.9.3: dependencies: color-name: 1.1.3 - dev: true - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: true - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true + color-name@1.1.3: {} - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true + color-name@1.1.4: {} - /color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: true + color-support@1.1.3: {} - /colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true + colorette@2.0.20: {} - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: true + commander@10.0.1: {} - /commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - dev: true + commander@11.1.0: {} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true + concat-map@0.0.1: {} - /config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + config-chain@1.1.13: dependencies: ini: 1.3.8 proto-list: 1.2.4 - dev: true - /configstore@6.0.0: - resolution: {integrity: sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==} - engines: {node: '>=12'} + configstore@6.0.0: dependencies: dot-prop: 6.0.1 graceful-fs: 4.2.10 unique-string: 3.0.0 write-file-atomic: 3.0.3 xdg-basedir: 5.1.0 - dev: true - /console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: true + console-control-strings@1.1.0: {} - /cosmiconfig@8.3.6: - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true + cosmiconfig@8.3.6: dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 - dev: true - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true - /crypto-random-string@4.0.0: - resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} - engines: {node: '>=12'} + crypto-random-string@4.0.0: dependencies: type-fest: 1.4.0 - dev: true - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.3.4: dependencies: ms: 2.1.2 - dev: true - /decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} + decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 - dev: true - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - dev: true + deep-extend@0.6.0: {} - /defer-to-connect@2.0.1: - resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} - engines: {node: '>=10'} - dev: true + defer-to-connect@2.0.1: {} - /delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: true + delegates@1.0.0: {} - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 - dev: true - /dot-prop@6.0.1: - resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} - engines: {node: '>=10'} + dot-prop@6.0.1: dependencies: is-obj: 2.0.0 - dev: true - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true + eastasianwidth@0.2.0: {} - /emoji-regex@10.3.0: - resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} - dev: true + emoji-regex@10.3.0: {} - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true + emoji-regex@8.0.0: {} - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true + emoji-regex@9.2.2: {} - /encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - requiresBuild: true + encoding@0.1.13: dependencies: iconv-lite: 0.6.3 - dev: true optional: true - /env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - dev: true + env-paths@2.2.1: {} - /err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - dev: true + err-code@2.0.3: {} - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - dev: true - - /escape-goat@4.0.0: - resolution: {integrity: sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==} - engines: {node: '>=12'} - dev: true - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true + escape-goat@4.0.0: {} - /eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - dev: true + escape-string-regexp@1.0.5: {} - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} + eventemitter3@5.0.1: {} + + execa@8.0.1: dependencies: cross-spawn: 7.0.3 get-stream: 8.0.1 @@ -798,103 +1972,60 @@ packages: onetime: 6.0.0 signal-exit: 4.1.0 strip-final-newline: 3.0.0 - dev: true - /exponential-backoff@3.1.1: - resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} - dev: true + exponential-backoff@3.1.1: {} - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true + fast-deep-equal@3.1.3: {} - /fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - dev: true + fast-diff@1.3.0: {} - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 - dev: true - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true + fast-json-stable-stringify@2.1.0: {} - /fast-memoize@2.5.2: - resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} - dev: true + fast-memoize@2.5.2: {} - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fastq@1.17.1: dependencies: reusify: 1.0.4 - dev: true - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 - dev: true - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + find-up@5.0.0: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - dev: true - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} + foreground-child@3.1.1: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 - dev: true - /form-data-encoder@2.1.4: - resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} - engines: {node: '>= 14.17'} - dev: true + form-data-encoder@2.1.4: {} - /fp-and-or@0.1.4: - resolution: {integrity: sha512-+yRYRhpnFPWXSly/6V4Lw9IfOV26uu30kynGJ03PW+MnjOEQe45RZ141QcS0aJehYBYA50GfCDnsRbFJdhssRw==} - engines: {node: '>=10'} - dev: true + fp-and-or@0.1.4: {} - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} + fs-minipass@2.1.0: dependencies: minipass: 3.3.6 - dev: true - /fs-minipass@3.0.3: - resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + fs-minipass@3.0.3: dependencies: minipass: 7.1.1 - dev: true - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true + fs.realpath@1.0.0: {} - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true + function-bind@1.1.2: {} - /gauge@4.0.4: - resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + gauge@4.0.4: dependencies: aproba: 2.0.0 color-support: 1.1.3 @@ -904,49 +2035,28 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wide-align: 1.1.5 - dev: true - /get-east-asian-width@1.2.0: - resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} - engines: {node: '>=18'} - dev: true + get-east-asian-width@1.2.0: {} - /get-stdin@8.0.0: - resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} - engines: {node: '>=10'} - dev: true + get-stdin@8.0.0: {} - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true + get-stream@6.0.1: {} - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - dev: true + get-stream@8.0.1: {} - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: true - /glob@10.3.14: - resolution: {integrity: sha512-4fkAqu93xe9Mk7le9v0y3VrPDqLKHarNi2s4Pv7f2yOvfhWfhc7hRPHC/JyqMqb8B/Dt/eGS4n7ykwf3fOsl8g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true + glob@10.3.14: dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 minimatch: 9.0.4 minipass: 7.1.1 path-scurry: 1.11.0 - dev: true - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + glob@7.2.3: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -954,29 +2064,20 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} + glob@8.1.0: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 minimatch: 5.1.6 once: 1.4.0 - dev: true - /global-dirs@3.0.1: - resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} - engines: {node: '>=10'} + global-dirs@3.0.1: dependencies: ini: 2.0.0 - dev: true - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 @@ -984,11 +2085,8 @@ packages: ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 - dev: true - /got@12.6.1: - resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} - engines: {node: '>=14.16'} + got@12.6.1: dependencies: '@sindresorhus/is': 5.6.0 '@szmarczak/http-timer': 5.0.1 @@ -1001,380 +2099,199 @@ packages: lowercase-keys: 3.0.0 p-cancelable: 3.0.0 responselike: 3.0.0 - dev: true - /graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - dev: true + graceful-fs@4.2.10: {} - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true + has-flag@3.0.0: {} - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true + has-flag@4.0.0: {} - /has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: true + has-unicode@2.0.1: {} - /has-yarn@3.0.0: - resolution: {integrity: sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + has-yarn@3.0.0: {} - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} + hasown@2.0.2: dependencies: function-bind: 1.1.2 - dev: true - /hosted-git-info@5.2.1: - resolution: {integrity: sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hosted-git-info@5.2.1: dependencies: lru-cache: 7.18.3 - dev: true - /hosted-git-info@6.1.1: - resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hosted-git-info@6.1.1: dependencies: lru-cache: 7.18.3 - dev: true - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: true + http-cache-semantics@4.1.1: {} - /http-proxy-agent@5.0.0: - resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} - engines: {node: '>= 6'} + http-proxy-agent@5.0.0: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true - /http2-wrapper@2.2.1: - resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} - engines: {node: '>=10.19.0'} + http2-wrapper@2.2.1: dependencies: quick-lru: 5.1.1 resolve-alpn: 1.2.1 - dev: true - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 debug: 4.3.4 transitivePeerDependencies: - supports-color - dev: true - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - dev: true + human-signals@5.0.0: {} - /humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + humanize-ms@1.2.1: dependencies: ms: 2.1.2 - dev: true - /husky@9.0.11: - resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} - engines: {node: '>=18'} - hasBin: true - dev: true + husky@9.0.11: {} - /iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - requiresBuild: true + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 - dev: true optional: true - /ignore-walk@6.0.5: - resolution: {integrity: sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ignore-walk@6.0.5: dependencies: minimatch: 9.0.4 - dev: true - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true + ignore@5.3.1: {} - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true - /import-lazy@4.0.0: - resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} - engines: {node: '>=8'} - dev: true + import-lazy@4.0.0: {} - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true + imurmurhash@0.1.4: {} - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - dev: true + indent-string@4.0.0: {} - /infer-owner@1.0.4: - resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} - dev: true + infer-owner@1.0.4: {} - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + inflight@1.0.6: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true + inherits@2.0.4: {} - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true + ini@1.3.8: {} - /ini@2.0.0: - resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} - engines: {node: '>=10'} - dev: true + ini@2.0.0: {} - /ini@4.1.2: - resolution: {integrity: sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true + ini@4.1.2: {} - /ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} + ip-address@9.0.5: dependencies: jsbn: 1.1.0 sprintf-js: 1.1.3 - dev: true - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true + is-arrayish@0.2.1: {} - /is-ci@3.0.1: - resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} - hasBin: true + is-ci@3.0.1: dependencies: ci-info: 3.9.0 - dev: true - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + is-core-module@2.13.1: dependencies: hasown: 2.0.2 - dev: true - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true + is-extglob@2.1.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true + is-fullwidth-code-point@3.0.0: {} - /is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - dev: true + is-fullwidth-code-point@4.0.0: {} - /is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} - engines: {node: '>=18'} + is-fullwidth-code-point@5.0.0: dependencies: get-east-asian-width: 1.2.0 - dev: true - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - dev: true - /is-installed-globally@0.4.0: - resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} - engines: {node: '>=10'} + is-installed-globally@0.4.0: dependencies: global-dirs: 3.0.1 is-path-inside: 3.0.3 - dev: true - /is-lambda@1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - dev: true + is-lambda@1.0.1: {} - /is-npm@6.0.0: - resolution: {integrity: sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + is-npm@6.0.0: {} - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true + is-number@7.0.0: {} - /is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - dev: true + is-obj@2.0.0: {} - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true + is-path-inside@3.0.3: {} - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + is-stream@3.0.0: {} - /is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - dev: true + is-typedarray@1.0.0: {} - /is-yarn-global@0.4.1: - resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} - engines: {node: '>=12'} - dev: true + is-yarn-global@0.4.1: {} - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true + isexe@2.0.0: {} - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} + jackspeak@2.3.6: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: true - /jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - dev: true + jju@1.4.0: {} - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true + js-tokens@4.0.0: {} - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true + js-yaml@4.1.0: dependencies: argparse: 2.0.1 - dev: true - /jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - dev: true + jsbn@1.1.0: {} - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true + json-buffer@3.0.1: {} - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true + json-parse-even-better-errors@2.3.1: {} - /json-parse-even-better-errors@3.0.2: - resolution: {integrity: sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true + json-parse-even-better-errors@3.0.2: {} - /json-parse-helpfulerror@1.0.3: - resolution: {integrity: sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==} + json-parse-helpfulerror@1.0.3: dependencies: jju: 1.4.0 - dev: true - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true + json-schema-traverse@0.4.1: {} - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true + json-schema-traverse@1.0.0: {} - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true + json5@2.2.3: {} - /jsonlines@0.1.1: - resolution: {integrity: sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==} - dev: true + jsonlines@0.1.1: {} - /jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - dev: true + jsonparse@1.3.1: {} - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 - dev: true - /kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: true + kleur@4.1.5: {} - /latest-version@7.0.0: - resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} - engines: {node: '>=14.16'} + latest-version@7.0.0: dependencies: package-json: 8.1.1 - dev: true - /lilconfig@3.0.0: - resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} - engines: {node: '>=14'} - dev: true + lilconfig@3.0.0: {} - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true + lines-and-columns@1.2.4: {} - /lint-staged@15.2.2: - resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} - engines: {node: '>=18.12.0'} - hasBin: true + lint-staged@15.2.2: dependencies: chalk: 5.3.0 commander: 11.1.0 @@ -1388,11 +2305,8 @@ packages: yaml: 2.3.4 transitivePeerDependencies: - supports-color - dev: true - /listr2@8.0.1: - resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} - engines: {node: '>=18.0.0'} + listr2@8.0.1: dependencies: cli-truncate: 4.0.0 colorette: 2.0.20 @@ -1400,59 +2314,34 @@ packages: log-update: 6.0.0 rfdc: 1.3.1 wrap-ansi: 9.0.0 - dev: true - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} + locate-path@6.0.0: dependencies: p-locate: 5.0.0 - dev: true - /lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true + lodash.truncate@4.4.2: {} - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true + lodash@4.17.21: {} - /log-update@6.0.0: - resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} - engines: {node: '>=18'} + log-update@6.0.0: dependencies: ansi-escapes: 6.2.0 cli-cursor: 4.0.0 slice-ansi: 7.1.0 strip-ansi: 7.1.0 wrap-ansi: 9.0.0 - dev: true - /lowercase-keys@3.0.0: - resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + lowercase-keys@3.0.0: {} - /lru-cache@10.2.2: - resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} - engines: {node: 14 || >=16.14} - dev: true + lru-cache@10.2.2: {} - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} + lru-cache@6.0.0: dependencies: yallist: 4.0.0 - dev: true - /lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - dev: true + lru-cache@7.18.3: {} - /make-fetch-happen@10.2.1: - resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + make-fetch-happen@10.2.1: dependencies: agentkeepalive: 4.5.0 cacache: 16.1.3 @@ -1473,11 +2362,8 @@ packages: transitivePeerDependencies: - bluebird - supports-color - dev: true - /make-fetch-happen@11.1.1: - resolution: {integrity: sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + make-fetch-happen@11.1.1: dependencies: agentkeepalive: 4.5.0 cacache: 17.1.4 @@ -1496,170 +2382,95 @@ packages: ssri: 10.0.6 transitivePeerDependencies: - supports-color - dev: true - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true + merge-stream@2.0.0: {} - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true + merge2@1.4.1: {} - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} + micromatch@4.0.5: dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: true - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true + mimic-fn@2.1.0: {} - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true + mimic-fn@4.0.0: {} - /mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - dev: true + mimic-response@3.1.0: {} - /mimic-response@4.0.0: - resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true + mimic-response@4.0.0: {} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - dev: true - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} + minimatch@5.1.6: dependencies: brace-expansion: 2.0.1 - dev: true - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 - dev: true - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true + minimist@1.2.8: {} - /minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} + minipass-collect@1.0.2: dependencies: minipass: 3.3.6 - dev: true - /minipass-fetch@2.1.2: - resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + minipass-fetch@2.1.2: dependencies: minipass: 3.3.6 minipass-sized: 1.0.3 minizlib: 2.1.2 optionalDependencies: encoding: 0.1.13 - dev: true - /minipass-fetch@3.0.5: - resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + minipass-fetch@3.0.5: dependencies: minipass: 7.1.1 minipass-sized: 1.0.3 minizlib: 2.1.2 optionalDependencies: encoding: 0.1.13 - dev: true - /minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} + minipass-flush@1.0.5: dependencies: minipass: 3.3.6 - dev: true - /minipass-json-stream@1.0.1: - resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} + minipass-json-stream@1.0.1: dependencies: jsonparse: 1.3.1 minipass: 3.3.6 - dev: true - /minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} + minipass-pipeline@1.2.4: dependencies: minipass: 3.3.6 - dev: true - /minipass-sized@1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} + minipass-sized@1.0.3: dependencies: minipass: 3.3.6 - dev: true - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} + minipass@3.3.6: dependencies: yallist: 4.0.0 - dev: true - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - dev: true + minipass@5.0.0: {} - /minipass@7.1.1: - resolution: {integrity: sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true + minipass@7.1.1: {} - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} + minizlib@2.1.2: dependencies: minipass: 3.3.6 yallist: 4.0.0 - dev: true - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - dev: true + mkdirp@1.0.4: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true + ms@2.1.2: {} - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: true + negotiator@0.6.3: {} - /node-gyp@9.4.1: - resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} - engines: {node: ^12.13 || ^14.13 || >=16} - hasBin: true + node-gyp@9.4.1: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.1 @@ -1675,42 +2486,25 @@ packages: transitivePeerDependencies: - bluebird - supports-color - dev: true - /nopt@6.0.0: - resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - hasBin: true + nopt@6.0.0: dependencies: abbrev: 1.1.1 - dev: true - /normalize-package-data@5.0.0: - resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + normalize-package-data@5.0.0: dependencies: hosted-git-info: 6.1.1 is-core-module: 2.13.1 semver: 7.6.0 validate-npm-package-license: 3.0.4 - dev: true - /normalize-url@8.0.0: - resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} - engines: {node: '>=14.16'} - dev: true + normalize-url@8.0.0: {} - /npm-bundled@3.0.1: - resolution: {integrity: sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + npm-bundled@3.0.1: dependencies: npm-normalize-package-bin: 3.0.1 - dev: true - /npm-check-updates@16.14.20: - resolution: {integrity: sha512-sYbIhun4DrjO7NFOTdvs11nCar0etEhZTsEjL47eM0TuiGMhmYughRCxG2SpGRmGAQ7AkwN7bw2lWzoE7q6yOQ==} - engines: {node: '>=14.14'} - hasBin: true + npm-check-updates@16.14.20: dependencies: '@types/semver-utils': 1.1.3 chalk: 5.3.0 @@ -1748,50 +2542,32 @@ packages: transitivePeerDependencies: - bluebird - supports-color - dev: true - /npm-install-checks@6.3.0: - resolution: {integrity: sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + npm-install-checks@6.3.0: dependencies: semver: 7.6.0 - dev: true - /npm-normalize-package-bin@3.0.1: - resolution: {integrity: sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true + npm-normalize-package-bin@3.0.1: {} - /npm-package-arg@10.1.0: - resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + npm-package-arg@10.1.0: dependencies: hosted-git-info: 6.1.1 proc-log: 3.0.0 semver: 7.6.0 validate-npm-package-name: 5.0.1 - dev: true - /npm-packlist@7.0.4: - resolution: {integrity: sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + npm-packlist@7.0.4: dependencies: ignore-walk: 6.0.5 - dev: true - /npm-pick-manifest@8.0.2: - resolution: {integrity: sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + npm-pick-manifest@8.0.2: dependencies: npm-install-checks: 6.3.0 npm-normalize-package-bin: 3.0.1 npm-package-arg: 10.1.0 semver: 7.6.0 - dev: true - /npm-registry-fetch@14.0.5: - resolution: {integrity: sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + npm-registry-fetch@14.0.5: dependencies: make-fetch-happen: 11.1.1 minipass: 5.0.0 @@ -1802,85 +2578,52 @@ packages: proc-log: 3.0.0 transitivePeerDependencies: - supports-color - dev: true - /npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 - dev: true - /npmlog@6.0.2: - resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + npmlog@6.0.2: dependencies: are-we-there-yet: 3.0.1 console-control-strings: 1.1.0 gauge: 4.0.4 set-blocking: 2.0.0 - dev: true - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + once@1.4.0: dependencies: wrappy: 1.0.2 - dev: true - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 - dev: true - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} + onetime@6.0.0: dependencies: mimic-fn: 4.0.0 - dev: true - /p-cancelable@3.0.0: - resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} - engines: {node: '>=12.20'} - dev: true + p-cancelable@3.0.0: {} - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - dev: true - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + p-locate@5.0.0: dependencies: p-limit: 3.1.0 - dev: true - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} + p-map@4.0.0: dependencies: aggregate-error: 3.1.0 - dev: true - /package-json@8.1.1: - resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} - engines: {node: '>=14.16'} + package-json@8.1.1: dependencies: got: 12.6.1 registry-auth-token: 5.0.2 registry-url: 6.0.1 semver: 7.6.0 - dev: true - /pacote@15.2.0: - resolution: {integrity: sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true + pacote@15.2.0: dependencies: '@npmcli/git': 4.1.0 '@npmcli/installed-package-contents': 2.1.0 @@ -1903,175 +2646,86 @@ packages: transitivePeerDependencies: - bluebird - supports-color - dev: true - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + parent-module@1.0.1: dependencies: callsites: 3.1.0 - dev: true - /parse-github-url@1.0.2: - resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==} - engines: {node: '>=0.10.0'} - hasBin: true - dev: true + parse-github-url@1.0.2: {} - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.23.5 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true + path-exists@4.0.0: {} - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true + path-is-absolute@1.0.1: {} - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true + path-key@3.1.1: {} - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true + path-key@4.0.0: {} - /path-scurry@1.11.0: - resolution: {integrity: sha512-LNHTaVkzaYaLGlO+0u3rQTz7QrHTFOuKyba9JMTQutkmtNew8dw8wOD7mTU/5fCPZzCWpfW0XnQKzY61P0aTaw==} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.11.0: dependencies: lru-cache: 10.2.2 minipass: 7.1.1 - dev: true - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true + path-type@4.0.0: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true + picomatch@2.3.1: {} - /pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - dev: true + pidtree@0.6.0: {} - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true + pluralize@8.0.0: {} - /prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} + prettier-linter-helpers@1.0.0: dependencies: fast-diff: 1.3.0 - dev: true - /prettier-plugin-solidity@1.3.1(prettier@3.2.5): - resolution: {integrity: sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==} - engines: {node: '>=16'} - peerDependencies: - prettier: '>=2.3.0' + prettier-plugin-solidity@1.3.1(prettier@3.2.5): dependencies: '@solidity-parser/parser': 0.17.0 prettier: 3.2.5 semver: 7.6.0 solidity-comments-extractor: 0.0.8 - dev: true - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - requiresBuild: true - dev: true + prettier@2.8.8: optional: true - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true + prettier@3.2.5: {} - /proc-log@3.0.0: - resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true + proc-log@3.0.0: {} - /progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - dev: true + progress@2.0.3: {} - /promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - dev: true + promise-inflight@1.0.1: {} - /promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} + promise-retry@2.0.1: dependencies: err-code: 2.0.3 retry: 0.12.0 - dev: true - /prompts-ncu@3.0.0: - resolution: {integrity: sha512-qyz9UxZ5MlPKWVhWrCmSZ1ahm2GVYdjLb8og2sg0IPth1KRuhcggHGuijz0e41dkx35p1t1q3GRISGH7QGALFA==} - engines: {node: '>= 14'} + prompts-ncu@3.0.0: dependencies: kleur: 4.1.5 sisteransi: 1.0.5 - dev: true - /proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - dev: true + proto-list@1.2.4: {} - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true + punycode@2.3.1: {} - /pupa@3.1.0: - resolution: {integrity: sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==} - engines: {node: '>=12.20'} + pupa@3.1.0: dependencies: escape-goat: 4.0.0 - dev: true - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true + queue-microtask@1.2.3: {} - /quick-lru@5.1.1: - resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} - engines: {node: '>=10'} - dev: true + quick-lru@5.1.1: {} - /rc-config-loader@4.1.3: - resolution: {integrity: sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==} + rc-config-loader@4.1.3: dependencies: debug: 4.3.4 js-yaml: 4.1.0 @@ -2079,186 +2733,103 @@ packages: require-from-string: 2.0.2 transitivePeerDependencies: - supports-color - dev: true - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true + rc@1.2.8: dependencies: deep-extend: 0.6.0 ini: 1.3.8 minimist: 1.2.8 strip-json-comments: 2.0.1 - dev: true - /read-package-json-fast@3.0.2: - resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + read-package-json-fast@3.0.2: dependencies: json-parse-even-better-errors: 3.0.2 npm-normalize-package-bin: 3.0.1 - dev: true - /read-package-json@6.0.4: - resolution: {integrity: sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + read-package-json@6.0.4: dependencies: glob: 10.3.14 json-parse-even-better-errors: 3.0.2 normalize-package-data: 5.0.0 npm-normalize-package-bin: 3.0.1 - dev: true - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: true - /registry-auth-token@5.0.2: - resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} - engines: {node: '>=14'} + registry-auth-token@5.0.2: dependencies: '@pnpm/npm-conf': 2.2.2 - dev: true - /registry-url@6.0.1: - resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} - engines: {node: '>=12'} + registry-url@6.0.1: dependencies: rc: 1.2.8 - dev: true - /remote-git-tags@3.0.0: - resolution: {integrity: sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==} - engines: {node: '>=8'} - dev: true + remote-git-tags@3.0.0: {} - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true + require-from-string@2.0.2: {} - /resolve-alpn@1.2.1: - resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - dev: true + resolve-alpn@1.2.1: {} - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true + resolve-from@4.0.0: {} - /responselike@3.0.0: - resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} - engines: {node: '>=14.16'} + responselike@3.0.0: dependencies: lowercase-keys: 3.0.0 - dev: true - /restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + restore-cursor@4.0.0: dependencies: onetime: 5.1.2 signal-exit: 3.0.7 - dev: true - /retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - dev: true + retry@0.12.0: {} - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true + reusify@1.0.4: {} - /rfdc@1.3.1: - resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - dev: true + rfdc@1.3.1: {} - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true + rimraf@3.0.2: dependencies: glob: 7.2.3 - dev: true - /rimraf@5.0.6: - resolution: {integrity: sha512-X72SgyOf+1lFnGM6gYcmZ4+jMOwuT4E4SajKQzUIlI7EoR5eFHMhS/wf8Ll0mN+w2bxcIVldrJQ6xT7HFQywjg==} - engines: {node: '>=14'} - hasBin: true + rimraf@5.0.6: dependencies: glob: 10.3.14 - dev: true - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - dev: true - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true + safe-buffer@5.2.1: {} - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - requiresBuild: true - dev: true + safer-buffer@2.1.2: optional: true - /semver-diff@4.0.0: - resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} - engines: {node: '>=12'} + semver-diff@4.0.0: dependencies: semver: 7.6.0 - dev: true - /semver-utils@1.1.4: - resolution: {integrity: sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==} - dev: true + semver-utils@1.1.4: {} - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true + semver@7.6.0: dependencies: lru-cache: 6.0.0 - dev: true - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true + set-blocking@2.0.0: {} - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: true - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true + shebang-regex@3.0.0: {} - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true + signal-exit@3.0.7: {} - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true + signal-exit@4.1.0: {} - /sigstore@1.9.0: - resolution: {integrity: sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true + sigstore@1.9.0: dependencies: '@sigstore/bundle': 1.1.0 '@sigstore/protobuf-specs': 0.2.1 @@ -2267,81 +2838,50 @@ packages: make-fetch-happen: 11.1.1 transitivePeerDependencies: - supports-color - dev: true - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true + sisteransi@1.0.5: {} - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true + slash@3.0.0: {} - /slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} + slice-ansi@4.0.0: dependencies: ansi-styles: 4.3.0 astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - dev: true - /slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} + slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 4.0.0 - dev: true - /slice-ansi@7.1.0: - resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} - engines: {node: '>=18'} + slice-ansi@7.1.0: dependencies: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 - dev: true - /smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true + smart-buffer@4.2.0: {} - /socks-proxy-agent@7.0.0: - resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} - engines: {node: '>= 10'} + socks-proxy-agent@7.0.0: dependencies: agent-base: 6.0.2 debug: 4.3.4 socks: 2.8.3 transitivePeerDependencies: - supports-color - dev: true - /socks@2.8.3: - resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + socks@2.8.3: dependencies: ip-address: 9.0.5 smart-buffer: 4.2.0 - dev: true - /solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5): - resolution: {integrity: sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==} - peerDependencies: - prettier: ^3.0.0 - prettier-plugin-solidity: ^1.0.0 + solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5): dependencies: '@prettier/sync': 0.3.0(prettier@3.2.5) prettier: 3.2.5 prettier-linter-helpers: 1.0.0 prettier-plugin-solidity: 1.3.1(prettier@3.2.5) - dev: true - /solhint@4.5.4: - resolution: {integrity: sha512-Cu1XiJXub2q1eCr9kkJ9VPv1sGcmj3V7Zb76B0CoezDOB9bu3DxKIFFH7ggCl9fWpEPD6xBmRLfZrYijkVmujQ==} - hasBin: true + solhint@4.5.4: dependencies: '@solidity-parser/parser': 0.18.0 ajv: 6.12.6 @@ -2365,166 +2905,99 @@ packages: prettier: 2.8.8 transitivePeerDependencies: - typescript - dev: true - /solidity-comments-extractor@0.0.8: - resolution: {integrity: sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==} - dev: true + solidity-comments-extractor@0.0.8: {} - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: true - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true + source-map@0.6.1: {} - /spawn-please@2.0.2: - resolution: {integrity: sha512-KM8coezO6ISQ89c1BzyWNtcn2V2kAVtwIXd3cN/V5a0xPYc1F/vydrRc01wsKFEQ/p+V1a4sw4z2yMITIXrgGw==} - engines: {node: '>=14'} + spawn-please@2.0.2: dependencies: cross-spawn: 7.0.3 - dev: true - /spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.17 - dev: true - /spdx-exceptions@2.5.0: - resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - dev: true + spdx-exceptions@2.5.0: {} - /spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 spdx-license-ids: 3.0.17 - dev: true - /spdx-license-ids@3.0.17: - resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==} - dev: true + spdx-license-ids@3.0.17: {} - /sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - dev: true + sprintf-js@1.1.3: {} - /ssri@10.0.6: - resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ssri@10.0.6: dependencies: minipass: 7.1.1 - dev: true - /ssri@9.0.1: - resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + ssri@9.0.1: dependencies: minipass: 3.3.6 - dev: true - /string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - dev: true + string-argv@0.3.2: {} - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + string-width@5.1.2: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: true - /string-width@7.1.0: - resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} - engines: {node: '>=18'} + string-width@7.1.0: dependencies: emoji-regex: 10.3.0 get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 - dev: true - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - dev: true - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - dev: true - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} + strip-ansi@7.1.0: dependencies: ansi-regex: 6.0.1 - dev: true - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true + strip-final-newline@3.0.0: {} - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - dev: true + strip-json-comments@2.0.1: {} - /strip-json-comments@5.0.1: - resolution: {integrity: sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==} - engines: {node: '>=14.16'} - dev: true + strip-json-comments@5.0.1: {} - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 - dev: true - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 - dev: true - /table@6.8.1: - resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} - engines: {node: '>=10.0.0'} + table@6.8.1: dependencies: ajv: 8.12.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} + tar@6.2.1: dependencies: chownr: 2.0.0 fs-minipass: 2.1.0 @@ -2532,94 +3005,54 @@ packages: minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 - dev: true - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true + text-table@0.2.0: {} - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: true - /tuf-js@1.1.7: - resolution: {integrity: sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + tuf-js@1.1.7: dependencies: '@tufjs/models': 1.0.4 debug: 4.3.4 make-fetch-happen: 11.1.1 transitivePeerDependencies: - supports-color - dev: true - /type-fest@1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} - dev: true + type-fest@1.4.0: {} - /type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - dev: true + type-fest@2.19.0: {} - /type-fest@3.13.1: - resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} - engines: {node: '>=14.16'} - dev: true + type-fest@3.13.1: {} - /typedarray-to-buffer@3.1.5: - resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + typedarray-to-buffer@3.1.5: dependencies: is-typedarray: 1.0.0 - dev: true - /unique-filename@2.0.1: - resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + unique-filename@2.0.1: dependencies: unique-slug: 3.0.0 - dev: true - /unique-filename@3.0.0: - resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + unique-filename@3.0.0: dependencies: unique-slug: 4.0.0 - dev: true - /unique-slug@3.0.0: - resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + unique-slug@3.0.0: dependencies: imurmurhash: 0.1.4 - dev: true - /unique-slug@4.0.0: - resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + unique-slug@4.0.0: dependencies: imurmurhash: 0.1.4 - dev: true - /unique-string@3.0.0: - resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} - engines: {node: '>=12'} + unique-string@3.0.0: dependencies: crypto-random-string: 4.0.0 - dev: true - /untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - dev: true + untildify@4.0.0: {} - /update-notifier@6.0.2: - resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} - engines: {node: '>=14.16'} + update-notifier@6.0.2: dependencies: boxen: 7.1.1 chalk: 5.3.0 @@ -2635,114 +3068,67 @@ packages: semver: 7.6.0 semver-diff: 4.0.0 xdg-basedir: 5.1.0 - dev: true - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + uri-js@4.4.1: dependencies: punycode: 2.3.1 - dev: true - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true + util-deprecate@1.0.2: {} - /validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - dev: true - /validate-npm-package-name@5.0.1: - resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: true + validate-npm-package-name@5.0.1: {} - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: true - /which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true + which@3.0.1: dependencies: isexe: 2.0.0 - dev: true - /wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + wide-align@1.1.5: dependencies: string-width: 4.2.3 - dev: true - /widest-line@4.0.1: - resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} - engines: {node: '>=12'} + widest-line@4.0.1: dependencies: string-width: 5.1.2 - dev: true - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + wrap-ansi@8.1.0: dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: true - /wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} + wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 string-width: 7.1.0 strip-ansi: 7.1.0 - dev: true - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true + wrappy@1.0.2: {} - /write-file-atomic@3.0.3: - resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + write-file-atomic@3.0.3: dependencies: imurmurhash: 0.1.4 is-typedarray: 1.0.0 signal-exit: 3.0.7 typedarray-to-buffer: 3.1.5 - dev: true - /xdg-basedir@5.1.0: - resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} - engines: {node: '>=12'} - dev: true + xdg-basedir@5.1.0: {} - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true + yallist@4.0.0: {} - /yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} - engines: {node: '>= 14'} - dev: true + yaml@2.3.4: {} - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true + yocto-queue@0.1.0: {} diff --git a/script/DeployEchoBlast.s.sol b/script/DeployEchoBlast.s.sol index 3558b3f..1ed8e34 100644 --- a/script/DeployEchoBlast.s.sol +++ b/script/DeployEchoBlast.s.sol @@ -17,11 +17,9 @@ contract DeployEchoBlast is Script { vm.etch(0x0000000000000000000000000000000000000100, address(yieldMock).code); uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + address deployer = vm.addr(deployerPrivateKey); vm.startBroadcast(deployerPrivateKey); - new EchoBlast({ - owner: address(0x213bE2f484Ab480db4f18b0Fe4C38e1C25877f09), - blastPointsAddress: address(0x2fc95838c71e76ec69ff817983BFf17c710F34E0) - }); + new EchoBlast({owner: deployer, blastPointsAddress: address(0x2fc95838c71e76ec69ff817983BFf17c710F34E0)}); vm.stopBroadcast(); } diff --git a/script/DeployEchoBlastMainnet.s.sol b/script/DeployEchoBlastMainnet.s.sol new file mode 100644 index 0000000..8bc1e3e --- /dev/null +++ b/script/DeployEchoBlastMainnet.s.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Script.sol"; +import "../src/EchoBlast.sol"; +import "../test/mock/YieldMock.sol"; + +contract DeployEchoBlastMainnet is Script { + // Exclude from coverage report + function test() public {} + + function run() external { + vm.createSelectFork(vm.envString("BLAST_RPC_URL")); + // Deploy mock of the precompile + YieldMock yieldMock = new YieldMock(); + // Set mock bytecode to the expected precompile address + vm.etch(0x0000000000000000000000000000000000000100, address(yieldMock).code); + + uint256 deployerPrivateKey = vm.envUint("MAINNET_PRIVATE_KEY"); + address deployer = vm.addr(deployerPrivateKey); + vm.startBroadcast(deployerPrivateKey); + new EchoBlast({owner: deployer, blastPointsAddress: address(0x2536FE9ab3F511540F2f9e2eC2A805005C3Dd800)}); + + vm.stopBroadcast(); + } +} diff --git a/script/MintNfts.s.sol b/script/MintNfts.s.sol index d9fce77..6d43ed0 100644 --- a/script/MintNfts.s.sol +++ b/script/MintNfts.s.sol @@ -9,33 +9,43 @@ contract MintNfts is Script { function test() public {} function run() external { - vm.startBroadcast(); - - // Use existing contract - Mocked721 YKPS = Mocked721(0xcFCEe3d83eac17bCaB91290c89f4B26Ce82f0238); - - YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 10); - YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 23); - YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 44); - YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 534); - YKPS.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 1203); - - YKPS.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 3); - YKPS.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 123); - YKPS.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 454); - - // Use existing contract - Mocked721 MAD = Mocked721(0xcb4d0fB16C735d2d41D050F14982fd782FA32a5B); - - MAD.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 31); - MAD.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 532); - MAD.safeMint(0x1D16E74EC651538aF22F4Ce59bB58Cb4a3E32898, 123); - - MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 5); - MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 63); - MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 324); - MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 65); - MAD.safeMint(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af, 767); + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + address minter = address(0x20F039821DE7Db6f543c7C07D419800Eb9Bd01Af); + + Mocked721 CBC = Mocked721(0xd91303F46C3f4883D9D74c703C15948e5E04E110); + Mocked721 BAYC = Mocked721(0x43bE93945E168A205D708F1A41A124fA302e1f76); + Mocked721 SORA = Mocked721(0x07d31999C2BAe29086133A5C93b07a481c5dDaea); + Mocked721 MAYC = Mocked721(0x4B8c2CE024D1cC1CFaE7FaA4A162bBfeAdBaEB41); + + // Mint NFTs + //CBC + CBC.safeMint(minter, 10); + CBC.safeMint(minter, 11); + CBC.safeMint(minter, 12); + CBC.safeMint(minter, 13); + CBC.safeMint(minter, 14); + + // BAYC + BAYC.safeMint(minter, 10); + BAYC.safeMint(minter, 11); + BAYC.safeMint(minter, 12); + BAYC.safeMint(minter, 13); + BAYC.safeMint(minter, 14); + + // SORA + SORA.safeMint(minter, 10); + SORA.safeMint(minter, 11); + SORA.safeMint(minter, 12); + SORA.safeMint(minter, 13); + SORA.safeMint(minter, 14); + + // MAYC + MAYC.safeMint(minter, 10); + MAYC.safeMint(minter, 11); + MAYC.safeMint(minter, 12); + MAYC.safeMint(minter, 13); + MAYC.safeMint(minter, 14); vm.stopBroadcast(); } diff --git a/script/TransferNfts.s.sol b/script/TransferNfts.s.sol new file mode 100644 index 0000000..3014dc5 --- /dev/null +++ b/script/TransferNfts.s.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import "forge-std/Script.sol"; +import "../test/mock/Mocked721.sol"; + +contract TransferNfts is Script { + // Exclude from coverage report + function test() public {} + + function run() external { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + console.log(block.chainid); + uint256 work2PrivateKey = vm.envUint("WORK2_PRIVATE_KEY"); + address deployer = vm.addr(deployerPrivateKey); + address work2 = vm.addr(work2PrivateKey); + Mocked721 MAYC = Mocked721(0x4B8c2CE024D1cC1CFaE7FaA4A162bBfeAdBaEB41); + MAYC.transferFrom(deployer, work2, 3); + vm.stopBroadcast(); + + vm.startBroadcast(work2PrivateKey); + MAYC.safeTransferFrom(work2, deployer, 3); + vm.stopBroadcast(); + } +} diff --git a/script/UpdateEchoFees.s.sol b/script/UpdateEchoFees.s.sol index b2b2fae..4e30da8 100644 --- a/script/UpdateEchoFees.s.sol +++ b/script/UpdateEchoFees.s.sol @@ -2,16 +2,16 @@ pragma solidity ^0.8.18; import "forge-std/Script.sol"; -import "../src/Echo.sol"; +import "../src/EchoBlast.sol"; contract UpdateEchoFees is Script { // Exclude from coverage report function test() public {} function run() external { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + uint256 deployerPrivateKey = vm.envUint("MAINNET_PRIVATE_KEY"); vm.startBroadcast(deployerPrivateKey); - Echo echo = Echo(0xB0904D81440EFCA27Ec61948c95f21D7d546F8C3); + EchoBlast echo = EchoBlast(0x538dD3e75d05B63dc81FEe587B8a4AA5Fde2cc95); echo.setFees(0.005 ether); vm.stopBroadcast(); }