diff --git a/.gitignore b/.gitignore index e8c12ff4..6e27dc7f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ node_modules # Hardhat Ignition default folder for deployments against a local node ignition/deployments/chain-31337 + +/lib +/forge-std diff --git a/.gitmodules b/.gitmodules index 888d42dc..690924b6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "lib/forge-std"] path = lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "lib/openzeppelin-contracts"] + path = lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 617e65c4..b8381609 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,8 @@ +Assignment 1 link [here](https://github.com/BlockheaderWeb3-Community/cohort-6/blob/main/assignments/Assignment1.md) + +Assignment 2 link [here](https://github.com/BlockheaderWeb3-Community/cohort-6/blob/main/assignments/Assignment2.md) @@ -12,4 +15,3 @@ - [ ] Tests - [ ] Documentation - diff --git a/README.md b/README.md index 9265b455..550b60e9 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,2 @@ -## Foundry - -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** - -Foundry consists of: - -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. - -## Documentation - -https://book.getfoundry.sh/ - -## Usage - -### Build - -```shell -$ forge build -``` - -### Test - -```shell -$ forge test -``` - -### Format - -```shell -$ forge fmt -``` - -### Gas Snapshots - -```shell -$ forge snapshot -``` - -### Anvil - -```shell -$ anvil -``` - -### Deploy - -```shell -$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key -``` - -### Cast - -```shell -$ cast -``` - -### Help - -```shell -$ forge --help -$ anvil --help -$ cast --help -``` +# Introduction to Foundry +Master the concepts to develop, test and deploy EVM contracts with Foundry \ No newline at end of file diff --git a/contracts/chainlink-integration/CrowdFundingV2.sol b/contracts/chainlink-integration/CrowdFundingV2.sol new file mode 100644 index 00000000..f82c6e03 --- /dev/null +++ b/contracts/chainlink-integration/CrowdFundingV2.sol @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; +import {console} from "forge-std/Test.sol"; +import "@chainlink/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol"; +import "../../contracts/with-foundry/RewardToken.sol"; +import "../../contracts/with-foundry/RewardNft.sol"; + +contract CrowdfundingV2 { + address public Owner; + uint public constant FUNDING_GOAL_IN_USD = 50000; + uint public constant NFT_THRESHOLD = 1000; + uint256 public totalFundsRaised; + bool public isFundingComplete; + + RewardToken public rewardToken; + RewardNft public rewardNFT; + uint256 public tokenRewardRate; + + // Contribution tracking + mapping(address => uint256) public contributions; + mapping(address => bool) public hasReceivedNFT; + + // Chainlink PriceFeed + AggregatorV3Interface priceFeed; + address public constant ETH_USD_ADDR = 0x694AA1769357215DE4FAC081bf1f309aDC325306; + // Events + event ContributionReceived(address indexed contributor, uint256 amount); + event TokenRewardSent(address indexed contributor, uint256 amount); + event NFTRewardSent(address indexed contributor, uint256 tokenId); + event FundsWithdrawn(address indexed projectOwner, uint256 amount); + + constructor(uint256 _tokenRewardRate, address _rewardToken, address _rewardNft) { + /** + * Network: Sepolia + * Data Feed: ETH/USD + * Address: 0x694AA1769357215DE4FAC081bf1f309aDC325306 + */ + priceFeed = AggregatorV3Interface(ETH_USD_ADDR); + Owner = msg.sender; + rewardToken = RewardToken(_rewardToken); + rewardNFT = RewardNft(_rewardNft); + tokenRewardRate = _tokenRewardRate; + } + + // function to retrieve ETH price in USD with Chainlink priceFeed + function getLatestPrice() public view returns (int256) { + ( + , + // uint80 roundID + int256 answer, // uint256 startedAt + , + , + + ) = // uint256 updatedAt + priceFeed.latestRoundData(); + + return answer; // Price has 8 decimals, e.g., 3000.00000000 + } + + function contribute() external payable returns (bool) { + require(msg.value > 0, "Contribution must be greater than 0"); + require(!isFundingComplete, "Funding goal already reached"); + + // Calculate contribution amount and process any refunds + + uint256 refundableAmount = _determineIfAmountIsRefundable(msg.value); + uint256 actualContribution = msg.value - refundableAmount; + + // check if refundable amount is > 0 + if (refundableAmount > 0) { + transferRefundableAmount(refundableAmount, msg.sender); + } + + // Update contribution record + // uint256 contributionsValue = msg.value - refundableAmount; + contributions[msg.sender] += actualContribution; + totalFundsRaised += actualContribution; + + // Check if funding goal is reached + if (totalFundsRaised >= FUNDING_GOAL_IN_USD) { + isFundingComplete = true; + } + + // Calculate token reward + uint256 tokenReward = calculateReward(actualContribution); + + if (tokenReward > 0) { + bool isTransfered = sendRewardToken(tokenReward, msg.sender); + require(isTransfered, "Token transfer failed"); + + // Check for NFT eligibility + if (checkNftEligibility(msg.sender)) { + mintNft(msg.sender); + } + + emit ContributionReceived(msg.sender, actualContribution); + return true; + } else { + return false; + } + } + + function checkNftEligibility(address _address) private view returns (bool) { + return contributions[_address] >= NFT_THRESHOLD && !hasReceivedNFT[_address]; + } + + function mintNft(address _contributor) private returns (bool) { + // require(checkNftEligibilty(_contributor), "Not eligible for NFT reward"); + uint256 tokenId = rewardNFT.mintNFT(_contributor); + hasReceivedNFT[_contributor] = true; + emit NFTRewardSent(_contributor, tokenId); + return true; + } + + function calculateReward(uint256 _value) private view returns (uint256) { + uint256 tokenReward = (_value * tokenRewardRate) / 1 ether; + return tokenReward; + } + + function sendRewardToken(uint256 _tokenReward, address _recipient) private returns (bool) { + bool success = rewardToken.transfer(_recipient, _tokenReward); + require(success, "Token transfer failed"); + emit TokenRewardSent(msg.sender, _tokenReward); + + return true; + } + + function _determineIfAmountIsRefundable(uint256 _contributionAmount) private view returns (uint256) { + // Calculate the remaining amount needed to complete the funding goal + uint256 amountToReachThreshold = FUNDING_GOAL_IN_USD - totalFundsRaised; + if (_contributionAmount >= amountToReachThreshold) { + // return the excess amount + uint256 refundAmount = _contributionAmount - amountToReachThreshold; + return refundAmount; + } + return 0; + } + + function transferRefundableAmount(uint256 _amount, address _contributor) private { + // uint256 refundable = _determineIfAmountIsRefundable(_amount); + uint256 refundable = _amount; + if (refundable > 0) { + (bool success, ) = _contributor.call{value: refundable}(""); + require(success, "Transfer failed"); + } + } + + function withdrawFunds() external { + require(msg.sender == Owner, "Only project owner can withdraw"); + require(isFundingComplete, "Funding goal not yet reached"); + require(address(this).balance > 0, "No funds to withdraw"); + + uint256 amount = address(this).balance; + payable(Owner).transfer(amount); + + emit FundsWithdrawn(Owner, amount); + } + + function getContribution(address contributor) external view returns (uint256) { + return contributions[contributor]; + } +} diff --git a/contracts/counter_alex.sol b/contracts/counter_alex.sol new file mode 100644 index 00000000..7a2d9f7c --- /dev/null +++ b/contracts/counter_alex.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.5.0 <0.9.0; + +/** + * @title Counter Contract + * @notice A simple counter contract that supports incrementing and decrementing operations. + * @dev Provides functions to increment, decrement and adjust the counter by a specified value. + */ + +contract Counter { + /** + * @notice The current count value. + * @dev Public state variable initialized to zero. + */ + uint public countVal = 0; + + /** + * @notice Retrieves the current count value. + * @return The current counter value. + */ + function getCount() public view returns (uint) { + return countVal; + } + + /** + * @notice Increments the counter by one. + * @dev Ensures that the counter does not exceed the maximum value defined by runner(). + */ + function increment() public { + uint maxValue = runner(); + require(countVal < maxValue); + countVal++; + } + + /** + * @notice Decrements the counter by one. + * @dev Prevents the counter from decrementing below zero. + */ + function decrement() public { + require(countVal > 0, "Counter cannot be negative"); + countVal--; + } + + /** + * @notice Increments the counter by a specified positive value. + * @param _val The value to add to the current count. + * @dev Validates that _val is greater than zero and that the resulting count does not exceed the maximum value. + */ + function incrementByVal(uint _val) public { + uint maxValue = runner(); + require(_val > 0, "Must be greater than zero"); + require(countVal + _val <= maxValue, "Counter cannot be negative"); + countVal += _val; + } + + /** + * @notice Decrements the counter by a specified positive value. + * @param _val The value to subtract from the current count. + * @dev Validates that _val is greater than zero and that the current count is sufficient to subtract _val without underflow. + */ + function decrementByVal(uint _val) public { + require(_val > 0, "Must be greater than zero"); + require(countVal >= _val, "Underflow: Cannot decrement below zero"); // Prevent underflow + + countVal -= _val; + } + + /** + * @notice Computes the maximum value for a uint256. + * @return The maximum possible value of a uint256. + * @dev Uses unchecked arithmetic to derive the maximum uint256 value. + */ + function runner() public pure returns (uint) { + unchecked { + return uint256(0) - 1; + } + } +} diff --git a/contracts/crowdfunding_alex.sol b/contracts/crowdfunding_alex.sol new file mode 100644 index 00000000..2447dc4f --- /dev/null +++ b/contracts/crowdfunding_alex.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +import "./reward_token.sol"; +import "./reward_nft_alex.sol"; +contract CrowdFund {} diff --git a/contracts/reward_nft_alex.sol b/contracts/reward_nft_alex.sol new file mode 100644 index 00000000..8c9600bc --- /dev/null +++ b/contracts/reward_nft_alex.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +contract RewardNFT { + // ... +} diff --git a/contracts/reward_token_alex.sol b/contracts/reward_token_alex.sol new file mode 100644 index 00000000..f2611882 --- /dev/null +++ b/contracts/reward_token_alex.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +contract RewardToken { + // ... +} diff --git a/contracts/student_registry_alex.sol b/contracts/student_registry_alex.sol new file mode 100644 index 00000000..867ecff5 --- /dev/null +++ b/contracts/student_registry_alex.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.5.0 <0.9.0; + +/// @title StudentRegistry +/// @dev A contract to manage student registration, attendance, and interests. +contract StudentRegister { + /// @dev Enum to represent student attendance status. + enum Attendance { + Absent, + Present + } + + /// @dev Struct to represent a student. + struct Student { + string Name; // Name of the student + Attendance attendance; // Attendance status of the student + string[] interest; // List of interests of the student + } + + /// @dev Address of the contract owner. + address public owner; + + /// @dev Mapping to store student data by their address. + mapping(address => Student) public students; + + /// @dev Event emitted when a new student is registered. + event StudentCreated(address indexed _studentAddress, string _name); + + /// @dev Event emitted when a student's attendance status is updated. + event AttendanceStatus(address indexed _studentAddress, Attendance _attendance); + + /// @dev Event emitted when a new interest is added to a student's profile. + event InterestAdded(address indexed _studentAddress, string _interest); + + /// @dev Event emitted when an interest is removed from a student's profile. + event InterestRemoved(address indexed _studentAddress, string _interest); + + /// @dev Modifier to restrict access to the contract owner. + modifier OnlyOwner() { + require(msg.sender == owner, "Owner only function"); + _; + } + + /// @dev Modifier to ensure a student with the given address exists. + modifier studentExists(address _studentaddr) { + require(bytes(students[_studentaddr].Name).length != 0, "The specified student does not exist."); + _; + } + + /// @dev Modifier to ensure a student with the given address does not exist. + modifier studentDoesNotExist(address _studentAddr) { + require(bytes(students[_studentAddr].Name).length == 0, "The specified student already exists."); + _; + } + + /// @dev Constructor to set the contract owner. + constructor() { + owner = msg.sender; + } + + /// @dev Registers a new student with a name, attendance status, and interests. + /// @param _name The name of the student. + /// @param _attendance The attendance status of the student. + /// @param _interests The list of interests of the student. + function registerStudent(string memory _name, Attendance _attendance, string[] memory _interests) public { + students[msg.sender].Name = _name; + students[msg.sender].attendance = _attendance; + students[msg.sender].interest = _interests; + + emit StudentCreated(msg.sender, _name); + } + + /// @dev Registers a new student with a default attendance status (Absent) and no interests. + /// @param _name The name of the student. + function registerNewStudent(string memory _name) public studentDoesNotExist(msg.sender) { + require(bytes(_name).length > 0, "The provided name is empty."); + students[msg.sender] = Student({Name: _name, attendance: Attendance.Absent, interest: new string[](0)}); + + emit StudentCreated(msg.sender, _name); + } + + /// @dev Marks the attendance of a student. + /// @param _address The address of the student. + /// @param _attendance The attendance status to set (Absent or Present). + function markAttendance(address _address, Attendance _attendance) public studentExists(_address) { + students[_address].attendance = _attendance; + emit AttendanceStatus(_address, _attendance); + } + + /// @dev Adds an interest to a student's profile. + /// @param _address The address of the student. + /// @param _interest The interest to add. + function addInterests(address _address, string memory _interest) public studentExists(_address) { + require(bytes(_interest).length > 0, "The provided interest is empty."); + require(bytes(_interest).length <= 5, "Maximum of 5 interests can be added."); + + for (uint256 i = 0; i < students[_address].interest.length; i++) { + require( + keccak256(bytes(students[_address].interest[i])) != keccak256(bytes(_interest)), + "Interest already exists." + ); + } + students[_address].interest.push(_interest); + emit InterestAdded(_address, _interest); + } + + /// @dev Removes an interest from a student's profile. + /// @param _addr The address of the student. + /// @param _interest The interest to remove. + function removeInterest(address _addr, string memory _interest) public studentExists(_addr) { + require(bytes(students[_addr].Name).length >= 0, "Interest cannot be empty."); + bool indexFound = false; + uint indexToRemove; + for (uint i = 0; i < students[_addr].interest.length; i++) { + if (keccak256(bytes(students[_addr].interest[i])) == keccak256(bytes(_interest))) { + indexFound = true; + indexToRemove = i; + break; + } + } + require(indexFound, "The provided interest does not exist."); + + // Move the last element into the place of the element to remove + students[_addr].interest[indexToRemove] = students[_addr].interest[students[_addr].interest.length - 1]; + + // Remove the last element + students[_addr].interest.pop(); + + emit InterestRemoved(_addr, _interest); + } + + /// @dev Retrieves the name of a student. + /// @param _addr The address of the student. + /// @return The name of the student. + function getStudentName(address _addr) public view studentExists(_addr) returns (string memory) { + return students[_addr].Name; + } + + /// @dev Retrieves the attendance status of a student. + /// @param _address The address of the student. + /// @return The attendance status of the student. + function getStudentAttendance(address _address) public view studentExists(_address) returns (Attendance) { + return students[_address].attendance; + } + + /// @dev Retrieves the list of interests of a student. + /// @param _address The address of the student. + /// @return The list of interests of the student. + function getStudentInterests(address _address) public view studentExists(_address) returns (string[] memory) { + return students[_address].interest; + } + + /// @dev Transfers ownership of the contract to a new address. + /// @param _newOwner The address of the new owner. + function transferOwnership(address _newOwner) public OnlyOwner { + owner = _newOwner; + } +} diff --git a/contracts/with-foundry/Counter.sol b/contracts/with-foundry/Counter.sol new file mode 100644 index 00000000..a28e5d32 --- /dev/null +++ b/contracts/with-foundry/Counter.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + address public owner; + + constructor() { + owner = msg.sender; + } + + modifier onlyOwner() { + require(msg.sender == owner, "Only owner can call this function"); + _; + } + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + // test increment function + function increment() public onlyOwner { + number++; + } + + // test decrement function + function decrement() public onlyOwner { + number--; + } + + // test add by value function + function add(uint256 x) public onlyOwner { + number += x; + } + + // test substract by value function + function sub(uint256 x) public onlyOwner { + number -= x; + } + + // test multiply by value function + function mul(uint256 x) public onlyOwner { + number *= x; + } + + // test divide by value function + function div(uint256 x) public onlyOwner { + number /= x; + } + + // test if a number is even + function isEven(uint256 x) public view onlyOwner returns (bool) { + return x % 2 == 0; + } + + // test if a number is odd + function isOdd(uint256 x) public view onlyOwner returns (bool) { + return x % 2 != 0; + } + + // test reset function + function reset() public onlyOwner { + number = 0; + } + + // test get total function + function getTotal() public view onlyOwner returns (uint256) { + return number; + } +} diff --git a/contracts/with-foundry/Crowdfunding.sol b/contracts/with-foundry/Crowdfunding.sol new file mode 100644 index 00000000..46157e35 --- /dev/null +++ b/contracts/with-foundry/Crowdfunding.sol @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; +import {console} from "forge-std/Test.sol"; + +import "./RewardToken.sol"; +import "./RewardNft.sol"; + +contract Crowdfunding { + address public Owner; + uint public constant FUNDING_GOAL = 50 ether; + uint public constant NFT_THRESHOLD = 5 ether; + uint256 public totalFundsRaised; + bool public isFundingComplete; + + RewardToken public rewardToken; + RewardNft public rewardNFT; + uint256 public tokenRewardRate; + + // Contribution tracking + mapping(address => uint256) public contributions; + mapping(address => bool) public hasReceivedNFT; + + // Events + event ContributionReceived(address indexed contributor, uint256 amount); + event TokenRewardSent(address indexed contributor, uint256 amount); + event NFTRewardSent(address indexed contributor, uint256 tokenId); + event FundsWithdrawn(address indexed projectOwner, uint256 amount); + + constructor(uint256 _tokenRewardRate, address _rewardToken, address _rewardNft) { + Owner = msg.sender; + rewardToken = RewardToken(_rewardToken); + rewardNFT = RewardNft(_rewardNft); + tokenRewardRate = _tokenRewardRate; + } + + function contribute() external payable returns (bool) { + require(msg.value > 0, "Contribution must be greater than 0"); + require(!isFundingComplete, "Funding goal already reached"); + + // Calculate contribution amount and process any refunds + + uint256 refundableAmount = _determineIfAmountIsRefundable(msg.value); + uint256 actualContribution = msg.value - refundableAmount; + + // check if refundable amount is > 0 + if (refundableAmount > 0) { + transferRefundableAmount(refundableAmount, msg.sender); + } + + // Update contribution record + // uint256 contributionsValue = msg.value - refundableAmount; + contributions[msg.sender] += actualContribution; + totalFundsRaised += actualContribution; + + // Check if funding goal is reached + if (totalFundsRaised >= FUNDING_GOAL) { + isFundingComplete = true; + } + + // Calculate token reward + uint256 tokenReward = calculateReward(actualContribution); + + if (tokenReward > 0) { + bool isTransfered = sendRewardToken(tokenReward, msg.sender); + require(isTransfered, "Token transfer failed"); + + // Check for NFT eligibility + if (checkNftEligibility(msg.sender)) { + mintNft(msg.sender); + } + + emit ContributionReceived(msg.sender, actualContribution); + return true; + } else { + return false; + } + } + + function checkNftEligibility(address _address) private view returns (bool) { + return contributions[_address] >= NFT_THRESHOLD && !hasReceivedNFT[_address]; + } + + function mintNft(address _contributor) private returns (bool) { + // require(checkNftEligibilty(_contributor), "Not eligible for NFT reward"); + uint256 tokenId = rewardNFT.mintNFT(_contributor); + hasReceivedNFT[_contributor] = true; + emit NFTRewardSent(_contributor, tokenId); + return true; + } + + function calculateReward(uint256 _value) private view returns (uint256) { + uint256 tokenReward = (_value * tokenRewardRate) / 1 ether; + return tokenReward; + } + + function sendRewardToken(uint256 _tokenReward, address _recipient) private returns (bool) { + bool success = rewardToken.transfer(_recipient, _tokenReward); + require(success, "Token transfer failed"); + emit TokenRewardSent(msg.sender, _tokenReward); + + return true; + } + + function _determineIfAmountIsRefundable(uint256 _contributionAmount) private view returns (uint256) { + // Calculate the remaining amount needed to complete the funding goal + uint256 amountToReachThreshold = FUNDING_GOAL - totalFundsRaised; + if (_contributionAmount >= amountToReachThreshold) { + // return the excess amount + uint256 refundAmount = _contributionAmount - amountToReachThreshold; + return refundAmount; + } + return 0; + } + + function transferRefundableAmount(uint256 _amount, address _contributor) private { + // uint256 refundable = _determineIfAmountIsRefundable(_amount); + uint256 refundable = _amount; + if (refundable > 0) { + (bool success, ) = _contributor.call{value: refundable}(""); + require(success, "Transfer failed"); + } + } + + function withdrawFunds() external { + require(msg.sender == Owner, "Only project owner can withdraw"); + require(isFundingComplete, "Funding goal not yet reached"); + require(address(this).balance > 0, "No funds to withdraw"); + + uint256 amount = address(this).balance; + payable(Owner).transfer(amount); + + emit FundsWithdrawn(Owner, amount); + } + + function getContribution(address contributor) external view returns (uint256) { + return contributions[contributor]; + } +} diff --git a/contracts/with-foundry/Payable.sol b/contracts/with-foundry/Payable.sol new file mode 100644 index 00000000..2adf6599 --- /dev/null +++ b/contracts/with-foundry/Payable.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +/// @title Payable Contract +/// @notice This contract allows users to deposit ETH and keeps track of investments +/// @dev Provides basic payable functionalities with fallback and receive functions +contract Payable { + /// @notice Address of the contract owner + address payable public owner; + + /// @notice Counter for tracking fallback calls + uint256 public counter; + + /// @notice Mapping to store investments made by investors + mapping(address investors => uint256 amount) internal investments; + + /// @notice Error for calling a function that does not exist + error FunctionDoesNotExit(); + + /// @notice Constructor to initialize the contract owner + constructor() payable { + owner = payable(msg.sender); + } + + /// @notice Deposits ETH into the contract and records the amount for the sender + /// @param amount The amount of ETH to deposit + /// @return The deposited amount + function deposit(uint256 amount) public payable returns (uint256) { + require(amount == msg.value, "msg.value must equal eth"); + investments[msg.sender] = amount; + return amount; + } + + /// @notice Retrieves the investment amount for a given investor + /// @param investor The address of the investor + /// @return investment The amount invested by the investor + function getInvestment( + address investor + ) public view returns (uint256 investment) { + investment = investments[investor]; + } + + /// @notice Returns the contract's ETH balance in ether + /// @return contractBalance The balance of the contract in ether + function getContractBalance() + public + view + returns (uint256 contractBalance) + { + contractBalance = address(this).balance / 1 ether; + } + + /// @notice Returns the sender's ETH balance + /// @return myEthBalance The ETH balance of the sender + function getMyEthBalance() public view returns (uint256 myEthBalance) { + myEthBalance = address(msg.sender).balance; + } + + /// @notice Receive function to accept ETH transfers + receive() external payable {} + + /// @notice Fallback function to handle incorrect function calls + fallback() external payable { + counter += 1; + } +} + +/// @title Funder Contract +/// @notice This contract enables sending ETH using transfer, send, and call methods +contract Funder { + /// @notice Error when ETH transfer fails + error FailedToSendEth(); + + /// @notice Sends ETH to a receiver using transfer + /// @param _receiver The recipient's address + function sendWithTransfer(address payable _receiver) public payable { + _receiver.transfer(msg.value); + } + + /// @notice Sends ETH to a receiver using send + /// @param _receiver The recipient's address + /// @return sent Boolean indicating if the transfer was successful + function sendWithSend( + address payable _receiver + ) public payable returns (bool sent) { + sent = _receiver.send(msg.value); + if (!sent) { + revert FailedToSendEth(); + } + } + + /// @notice Sends ETH to a receiver using call + /// @param _receiver The recipient's address + /// @return sent Boolean indicating if the transfer was successful + /// @return data The returned data from the call + function sendWithCall( + address payable _receiver + ) public payable returns (bool sent, bytes memory data) { + (sent, data) = _receiver.call{value: msg.value}(""); + require(sent, "failed to send eth"); + } + + /// @notice Calls the deposit function of `Payable` contract + /// @param _payableContractAddress The address of the payable contract + function callDeposit( + address payable _payableContractAddress + ) public payable { + uint256 amount = msg.value; + (bool success, bytes memory data) = _payableContractAddress.call{ + value: amount + }(abi.encodeWithSignature("deposit(uint256)", amount)); + require(success, "call failed"); + } +} diff --git a/contracts/with-foundry/RewardNft.sol b/contracts/with-foundry/RewardNft.sol new file mode 100644 index 00000000..fc805d20 --- /dev/null +++ b/contracts/with-foundry/RewardNft.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.17; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +// import "@openzeppelin/contracts/utils/Counters.sol"; +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; + +contract RewardNft is ERC721 { + // using Counters for Counters.Counter; + using Strings for uint256; + + uint256 public counter; + + address public owner; + + // Counters.Counter private _nftIds; + + uint256 public constant MAX_SUPPLY = 10; + + uint256 public totalMinted; + + string public uri; + + constructor( + string memory name_, + string memory symbol_, + string memory _uri + ) ERC721(name_, symbol_) { + uri = _uri; + owner = msg.sender; + } + + // function mintNFT(address minter) external { + // uint256 newTokenId = _nftIds.current(); + // require(newTokenId <= MAX_SUPPLY, "limit exceeded"); + // _safeMint(minter, newTokenId); + // _nftIds.increment(); + // totalMinted += 1; + // } + + function mintNFT(address to) public returns (uint256) { + uint256 currentCount = counter; + if (to == address(0)) { + revert ERC721InvalidReceiver(address(0)); + } + address previousOwner = _update(to, currentCount, address(0)); + counter++; + if (previousOwner != address(0)) { + revert ERC721InvalidSender(address(0)); + } + + return counter; + } + + function getTotalMinted() public view returns (uint256) { + return totalMinted; + } + + function _baseURI() internal view override returns (string memory) { + return uri; + } + + function setBaseUri(string memory _uri) public { + uri = _uri; + } + + // function tokenURI( + // uint256 tokenId + // ) public view override returns (string memory) { + // _requireMinted(tokenId); + + // string memory baseURI = _baseURI(); + // return + // bytes(baseURI).length > 0 + // ? string(abi.encodePacked(baseURI, tokenId.toString(), ".json")) + // : ""; + // } + + // function setTokenURI() public { + // _setTokenURI( + // totalMinted, + // "ipfs://QmeYhWhdX1ALiF5AeaHM5VwAR6XEUqL58kmdEx8GxxPkXk" + // ); + // } +} diff --git a/contracts/with-foundry/RewardToken.sol b/contracts/with-foundry/RewardToken.sol new file mode 100644 index 00000000..c4502036 --- /dev/null +++ b/contracts/with-foundry/RewardToken.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/** + * @title RewardToken - Simplified ERC20 + * @dev ERC20 token used as a reward for crowdfunding contributors + */ +contract RewardToken { + string public name = "RewardToken"; + string public symbol = "CRWD"; + uint8 public decimals = 18; + uint256 private _totalSupply; + + // Owner of the contract + address public owner; + // Only the crowdfunding contract can mint tokens + address public crowdfundingContract; + + // Balances for each account + mapping(address => uint256) private _balances; + // Allowances for each account + mapping(address => mapping(address => uint256)) private _allowances; + + // Events + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval( + address indexed owner, + address indexed spender, + uint256 value + ); + + // Modifier to restrict functions to owner + modifier onlyOwner() { + require(msg.sender == owner, "Not authorized"); + _; + } + + constructor() { + owner = msg.sender; + mintAllToOwner(); + } + + function setCrowdfundingContract( + address _crowdfundingContract + ) external onlyOwner { + crowdfundingContract = _crowdfundingContract; + } + + function totalSupply() external view returns (uint256) { + return _totalSupply; + } + + function balanceOf(address account) external view returns (uint256) { + return _balances[account]; + } + + // function mintReward(address to, uint256 amount) external { + // require( + // msg.sender == crowdfundingContract, + // "Only crowdfunding contract can mint" + // ); + // _mint(to, amount); + // } + + function mintAllToOwner() private onlyOwner { + // _mint(owner, _totalSupply); + _mint(owner, 5000); + } + + function transfer( + address recipient, + uint256 amount + ) external returns (bool) { + _transfer(msg.sender, recipient, amount); + return true; + } + + function approve(address spender, uint256 amount) external returns (bool) { + _approve(msg.sender, spender, amount); + return true; + } + + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][msg.sender]; + require( + currentAllowance >= amount, + "Transfer amount exceeds allowance" + ); + _approve(sender, msg.sender, currentAllowance - amount); + + return true; + } + + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal { + require(sender != address(0), "Transfer from the zero address"); + require(recipient != address(0), "Transfer to the zero address"); + require(_balances[sender] >= amount, "Transfer amount exceeds balance"); + + _balances[sender] -= amount; + _balances[recipient] += amount; + + emit Transfer(sender, recipient, amount); + } + + function _mint(address account, uint256 amount) private { + require(msg.sender == owner, "Only owner can mint"); + require(account != address(0), "Mint to the zero address"); + + _totalSupply += amount; + _balances[account] += amount; + + emit Transfer(address(0), account, amount); + } + + function _approve( + address _owner, + address spender, + uint256 amount + ) internal { + require(_owner != address(0), "Approve from the zero address"); + require(spender != address(0), "Approve to the zero address"); + + _allowances[_owner][spender] = amount; + + emit Approval(_owner, spender, amount); + } +} diff --git a/foundry.toml b/foundry.toml index 06eeab42..482dbce7 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,9 +2,21 @@ src = "src" out = "artifacts" libs = ["node_modules", "lib"] +# eth-rpc-url = "https://sepolia.infura.io" +# solc = ">=0.6.2, <0.9.0" remappings = [ "eth-gas-reporter/=node_modules/eth-gas-reporter/", "hardhat/=node_modules/hardhat/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "@chainlink/=lib/chainlink-local/lib/chainlink-brownie-contracts/", ] +# [rpc_endpoints] +# sepolia = "https://eth-sepolia.g.alchemy.com/v2/KX1L8OUxzzPpA2BK0oa2rRSbunp8M2aN" +# fork_block_number = 7887153 + +[fmt] +line_length = 100 +tab_width = 2 +bracket_spacing = true # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/lib/chainlink-local b/lib/chainlink-local new file mode 160000 index 00000000..7d8b2f88 --- /dev/null +++ b/lib/chainlink-local @@ -0,0 +1 @@ +Subproject commit 7d8b2f888e1f10c8841ccd9e0f4af0f5baf11dab diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts new file mode 160000 index 00000000..ca7a4e39 --- /dev/null +++ b/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit ca7a4e39de0860bbaadf95824207886e6de9fa64 diff --git a/package-lock.json b/package-lock.json index 1c868eb5..4b2cd6f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,8 @@ "": { "name": "Cohort-6", "dependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.7" + "@nomicfoundation/hardhat-chai-matchers": "^2.0.7", + "glob": "^11.0.1" }, "devDependencies": { "@nomicfoundation/hardhat-ignition-ethers": "^0.15.9", @@ -679,7 +680,7 @@ "@ethersproject/logger": "^5.7.0", "@ethersproject/properties": "^5.7.0", "bn.js": "^5.2.1", - "elliptic": "6.5.4", + "elliptic": ">=6.6.1", "hash.js": "1.1.7" } }, @@ -872,6 +873,102 @@ "node": ">=14" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -929,9 +1026,9 @@ } }, "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "license": "MIT" }, "node_modules/@metamask/eth-sig-util/node_modules/ethereumjs-util": { @@ -943,7 +1040,7 @@ "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", "create-hash": "^1.1.2", - "elliptic": "^6.5.2", + "elliptic": ">=6.6.1", "ethereum-cryptography": "^0.1.3", "ethjs-util": "0.1.6", "rlp": "^2.2.3" @@ -1032,6 +1129,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.7.0.tgz", "integrity": "sha512-+Zyu7TE47TGNcPhOfWLPA/zISs32WDMXrhSWdWYyPHDVn/Uux5TVuOeScKb0BR/R8EJ+leR8COUF/EGxvDOVKg==", + "license": "MIT", "dependencies": { "@nomicfoundation/edr-darwin-arm64": "0.7.0", "@nomicfoundation/edr-darwin-x64": "0.7.0", @@ -1049,6 +1147,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.7.0.tgz", "integrity": "sha512-vAH20oh4GaSB/iQFTRcoO8jLc0CLd9XuLY9I7vtcqZWAiM4U1J4Y8cu67PWmtxbvUQOqXR7S6FtAr8/AlWm14g==", + "license": "MIT", "engines": { "node": ">= 18" } @@ -1057,6 +1156,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.7.0.tgz", "integrity": "sha512-WHDdIrPvLlgXQr2eKypBM5xOZAwdxhDAEQIvEMQL8tEEm2qYW2bliUlssBPrs8E3bdivFbe1HizImslMAfU3+g==", + "license": "MIT", "engines": { "node": ">= 18" } @@ -1065,6 +1165,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.7.0.tgz", "integrity": "sha512-WXpJB54ukz1no7gxCPXVEw9pgl/9UZ/WO3l1ctyv/T7vOygjqA4SUd6kppTs6MNXAuTiisPtvJ/fmvHiMBLrsw==", + "license": "MIT", "engines": { "node": ">= 18" } @@ -1073,6 +1174,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.7.0.tgz", "integrity": "sha512-1iZYOcEgc+zJI7JQrlAFziuy9sBz1WgnIx3HIIu0J7lBRZ/AXeHHgATb+4InqxtEx9O3W8A0s7f11SyFqJL4Aw==", + "license": "MIT", "engines": { "node": ">= 18" } @@ -1081,6 +1183,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.7.0.tgz", "integrity": "sha512-wSjC94WcR5MM8sg9w3OsAmT6+bbmChJw6uJKoXR3qscps/jdhjzJWzfgT0XGRq3XMUfimyafW2RWOyfX3ouhrQ==", + "license": "MIT", "engines": { "node": ">= 18" } @@ -1089,6 +1192,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.7.0.tgz", "integrity": "sha512-Us22+AZ7wkG1mZwxqE4S4ZcuwkEA5VrUiBOJSvKHGOgy6vFvB/Euh5Lkp4GovwjrtiXuvyGO2UmtkzymZKDxZw==", + "license": "MIT", "engines": { "node": ">= 18" } @@ -1097,6 +1201,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.7.0.tgz", "integrity": "sha512-HAry0heTsWkzReVtjHwoIq3BgFCvXpVhJ5qPmTnegZGsr/KxqvMmHyDMifzKao4bycU8yrpTSyOiAJt27RWjzQ==", + "license": "MIT", "engines": { "node": ">= 18" } @@ -1167,9 +1272,9 @@ } }, "node_modules/@nomicfoundation/hardhat-chai-matchers": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.7.tgz", - "integrity": "sha512-RQfsiTwdf0SP+DtuNYvm4921X6VirCQq0Xyh+mnuGlTwEFSPZ/o27oQC+l+3Y/l48DDU7+ZcYBR+Fp+Rp94LfQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.8.tgz", + "integrity": "sha512-Z5PiCXH4xhNLASROlSUOADfhfpfhYO6D7Hn9xp8PddmHey0jq704cr6kfU8TRrQ4PUZbpfsZadPj+pCfZdjPIg==", "license": "MIT", "dependencies": { "@types/chai-as-promised": "^7.1.3", @@ -1185,9 +1290,9 @@ } }, "node_modules/@nomicfoundation/hardhat-ethers": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.6.tgz", - "integrity": "sha512-/xzkFQAaHQhmIAYOQmvHBPwL+NkwLzT9gRZBsgWUYeV+E6pzXsBQsHfRYbAZ3XEYare+T7S+5Tg/1KDJgepSkA==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.8.tgz", + "integrity": "sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==", "license": "MIT", "peer": true, "dependencies": { @@ -1235,9 +1340,9 @@ } }, "node_modules/@nomicfoundation/hardhat-network-helpers": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.11.tgz", - "integrity": "sha512-uGPL7QSKvxrHRU69dx8jzoBvuztlLCtyFsbgfXIwIjnO3dqZRz2GNMHJoO3C3dIiUNM6jdNF4AUnoQKDscdYrA==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.12.tgz", + "integrity": "sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==", "dev": true, "license": "MIT", "peer": true, @@ -1276,9 +1381,9 @@ } }, "node_modules/@nomicfoundation/hardhat-verify": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.8.tgz", - "integrity": "sha512-x/OYya7A2Kcz+3W/J78dyDHxr0ezU23DKTrRKfy5wDPCnePqnr79vm8EXqX3gYps6IjPBYyGPZ9K6E5BnrWx5Q==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.12.tgz", + "integrity": "sha512-Lg3Nu7DCXASQRVI/YysjuAX2z8jwOCbS0w5tz2HalWGSTZThqA0v9N0v0psHbKNqzPJa8bNOeapIVSziyJTnAg==", "dev": true, "license": "MIT", "peer": true, @@ -1286,9 +1391,9 @@ "@ethersproject/abi": "^5.1.2", "@ethersproject/address": "^5.0.2", "cbor": "^8.1.0", - "chalk": "^2.4.2", "debug": "^4.1.1", "lodash.clonedeep": "^4.5.0", + "picocolors": "^1.1.0", "semver": "^6.3.0", "table": "^6.8.0", "undici": "^5.14.0" @@ -1297,91 +1402,6 @@ "hardhat": "^2.0.4" } }, - "node_modules/@nomicfoundation/hardhat-verify/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@nomicfoundation/hardhat-verify/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@nomicfoundation/hardhat-verify/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@nomicfoundation/hardhat-verify/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@nomicfoundation/hardhat-verify/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@nomicfoundation/hardhat-verify/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@nomicfoundation/hardhat-verify/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@nomicfoundation/ignition-core": { "version": "0.15.9", "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-core/-/ignition-core-0.15.9.tgz", @@ -1536,9 +1556,9 @@ } }, "node_modules/@scure/base": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", - "integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" @@ -1850,18 +1870,18 @@ } }, "node_modules/@types/bn.js": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", - "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", + "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/chai": { - "version": "4.3.16", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.16.tgz", - "integrity": "sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==", + "version": "4.3.20", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", + "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", "license": "MIT" }, "node_modules/@types/chai-as-promised": { @@ -1922,20 +1942,20 @@ "peer": true }, "node_modules/@types/mocha": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.7.tgz", - "integrity": "sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==", + "version": "10.0.10", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", + "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", "dev": true, "license": "MIT", "peer": true }, "node_modules/@types/node": { - "version": "20.14.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", - "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", + "version": "22.13.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.2.tgz", + "integrity": "sha512-Z+r8y3XL9ZpI2EY52YYygAFmo2/oWfNSj4BCpAXE2McAexDk8VcnBMGC9Djn9gTKt4d2T/hhXqmPzo4hfIXtTg==", "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/@types/pbkdf2": { @@ -1956,9 +1976,9 @@ "peer": true }, "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", "dev": true, "license": "MIT", "peer": true @@ -1981,9 +2001,9 @@ "peer": true }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "devOptional": true, "license": "MIT", "peer": true, @@ -1995,9 +2015,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "devOptional": true, "license": "MIT", "peer": true, @@ -2261,9 +2281,9 @@ } }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "dev": true, "license": "MIT", "peer": true, @@ -2355,15 +2375,12 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "license": "MIT", - "peer": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -2445,19 +2462,31 @@ "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -2571,27 +2600,18 @@ } }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" } }, "node_modules/ci-info": { @@ -2601,13 +2621,16 @@ "license": "MIT" }, "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/clean-stack": { @@ -3023,6 +3046,20 @@ "license": "MIT", "peer": true }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/crypt": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", @@ -3042,12 +3079,12 @@ "peer": true }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3101,25 +3138,6 @@ "license": "MIT", "peer": true }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3176,6 +3194,28 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, "node_modules/elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -3192,9 +3232,9 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "license": "MIT" }, "node_modules/emoji-regex": { @@ -3226,15 +3266,12 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", "peer": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -3250,10 +3287,24 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", "engines": { "node": ">=6" @@ -3489,14 +3540,14 @@ } }, "node_modules/ethereum-bloom-filters/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", "dev": true, "license": "MIT", "peer": true, "engines": { - "node": ">= 16" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -3509,7 +3560,7 @@ "license": "MIT", "dependencies": { "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", + "@types/secp256k1": ">=4.0.4", "blakejs": "^1.1.0", "browserify-aes": "^1.2.0", "bs58check": "^2.1.2", @@ -3521,7 +3572,7 @@ "randombytes": "^2.1.0", "safe-buffer": "^5.1.2", "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", + "secp256k1": ">=4.0.4", "setimmediate": "^1.0.5" } }, @@ -3529,6 +3580,7 @@ "version": "0.6.8", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "deprecated": "This library has been deprecated and usage is discouraged.", "license": "MIT", "dependencies": { "bn.js": "^4.11.8", @@ -3545,9 +3597,9 @@ } }, "node_modules/ethereumjs-abi/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "license": "MIT" }, "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { @@ -3584,9 +3636,9 @@ } }, "node_modules/ethers": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", - "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", + "version": "6.13.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", + "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", "funding": [ { "type": "individual", @@ -3603,9 +3655,9 @@ "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", - "@types/node": "18.15.13", + "@types/node": "22.7.5", "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", + "tslib": "2.7.0", "ws": "8.17.1" }, "engines": { @@ -3613,9 +3665,19 @@ } }, "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ethers/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT", "peer": true }, @@ -3676,9 +3738,9 @@ "peer": true }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "peer": true, @@ -3687,7 +3749,7 @@ "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -3702,17 +3764,27 @@ "peer": true }, "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", "peer": true }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", "dev": true, "license": "ISC", "peer": true, @@ -3750,6 +3822,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -3771,9 +3844,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -3790,10 +3863,26 @@ } } }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "license": "MIT", "peer": true, @@ -3886,18 +3975,23 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3917,6 +4011,21 @@ "node": ">=4" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ghost-testrpc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", @@ -4018,23 +4127,23 @@ } }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", + "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", "license": "ISC", - "peer": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4082,6 +4191,20 @@ "node": ">=6" } }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/globby": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", @@ -4103,15 +4226,64 @@ "node": ">=8" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/globby/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "get-intrinsic": "^1.1.3" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/globby/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globby/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4285,20 +4457,6 @@ "@scure/base": "~1.1.0" } }, - "node_modules/hardhat/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/hardhat/node_modules/ethereum-cryptography": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", @@ -4334,18 +4492,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/hardhat/node_modules/readdirp": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz", - "integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/hardhat/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -4385,38 +4531,10 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", "peer": true, @@ -4571,9 +4689,9 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "peer": true, @@ -4747,9 +4865,22 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.3.tgz", + "integrity": "sha512-oSwM7q8PTHQWuZAlp995iPpPJ4Vkl7qT0ZRD+9duL9j2oBy6KcTfyxc8mEuHJYC+z/kbps80aJLkaNzTOrf/kw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/js-sha3": { "version": "0.8.0", @@ -4781,6 +4912,7 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", + "license": "MIT", "engines": { "node": ">=7.10.1" } @@ -4822,9 +4954,9 @@ } }, "node_modules/jsonschema": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", + "integrity": "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==", "dev": true, "license": "MIT", "peer": true, @@ -4888,6 +5020,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -4924,6 +5057,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", "license": "MIT", "peer": true }, @@ -4967,6 +5101,15 @@ "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", "license": "MIT" }, + "node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4983,6 +5126,17 @@ "license": "MIT", "peer": true }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -5022,9 +5176,9 @@ "peer": true }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "peer": true, @@ -5074,17 +5228,18 @@ "license": "MIT" }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "license": "ISC", - "peer": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -5098,6 +5253,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -5122,9 +5286,9 @@ } }, "node_modules/mocha": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.0.tgz", - "integrity": "sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", "license": "MIT", "dependencies": { "ansi-colors": "^4.1.3", @@ -5156,13 +5320,28 @@ "node": ">= 14.0.0" } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/mocha/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, "node_modules/mocha/node_modules/glob": { @@ -5197,11 +5376,17 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" + "node_modules/mocha/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", @@ -5219,9 +5404,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/ndjson": { @@ -5271,9 +5456,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", "license": "MIT", "bin": { "node-gyp-build": "bin.js", @@ -5351,9 +5536,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "peer": true, @@ -5365,9 +5550,9 @@ } }, "node_modules/obliterator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", + "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", "license": "MIT" }, "node_modules/once": { @@ -5417,6 +5602,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -5431,6 +5617,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -5456,6 +5643,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", @@ -5467,6 +5660,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", "engines": { "node": ">=8" } @@ -5482,12 +5676,37 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -5528,7 +5747,8 @@ "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -5623,14 +5843,14 @@ "peer": true }, "node_modules/qs": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", - "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "dev": true, "license": "BSD-3-Clause", "peer": true, "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -5700,15 +5920,16 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.1.tgz", + "integrity": "sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==", "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/rechoir": { @@ -5738,6 +5959,32 @@ "node": ">=6.0.0" } }, + "node_modules/recursive-readdir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/recursive-readdir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", @@ -5943,6 +6190,18 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/sc-istanbul/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/sc-istanbul/node_modules/glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", @@ -6003,6 +6262,20 @@ "node": ">=4" } }, + "node_modules/sc-istanbul/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/sc-istanbul/node_modules/resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -6025,6 +6298,20 @@ "node": ">=0.8.0" } }, + "node_modules/sc-istanbul/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", @@ -6032,20 +6319,47 @@ "license": "MIT" }, "node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "version": ">=4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" } }, + "node_modules/secp256k1/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" + }, + "node_modules/secp256k1/node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/secp256k1/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "license": "MIT" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -6064,25 +6378,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -6123,6 +6418,27 @@ "node": "*" } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", @@ -6142,18 +6458,106 @@ "node": ">=4" } }, + "node_modules/shelljs/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/shelljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/shelljs/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" @@ -6162,6 +6566,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -6231,15 +6668,15 @@ } }, "node_modules/solidity-coverage": { - "version": "0.8.12", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.12.tgz", - "integrity": "sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw==", + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.14.tgz", + "integrity": "sha512-ItAAObe5GaEOp20kXC2BZRnph+9P7Rtoqg2mQc2SXGEHgSDF2wWd1Wxz3ntzQWXkbCtIIGdJT918HG00cObwbA==", "dev": true, "license": "ISC", "peer": true, "dependencies": { "@ethersproject/abi": "^5.0.9", - "@solidity-parser/parser": "^0.18.0", + "@solidity-parser/parser": "^0.19.0", "chalk": "^2.4.2", "death": "^1.1.0", "difflib": "^0.2.4", @@ -6266,9 +6703,9 @@ } }, "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", - "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.19.0.tgz", + "integrity": "sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA==", "dev": true, "license": "MIT", "peer": true @@ -6372,9 +6809,9 @@ } }, "node_modules/solidity-coverage/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, "license": "ISC", "peer": true, @@ -6523,6 +6960,21 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -6535,6 +6987,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -6600,9 +7065,9 @@ } }, "node_modules/table": { - "version": "6.8.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", - "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, "license": "BSD-3-Clause", "peer": true, @@ -6689,16 +7154,17 @@ "peer": true }, "node_modules/then-request/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz", + "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "mime-types": "^2.1.12", + "safe-buffer": "^5.2.1" }, "engines": { "node": ">= 0.12" @@ -6719,6 +7185,7 @@ "version": "0.2.10", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "license": "MIT", "dependencies": { "fdir": "^6.4.2", "picomatch": "^4.0.2" @@ -6731,6 +7198,7 @@ "version": "6.4.3", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -6744,6 +7212,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", "engines": { "node": ">=12" }, @@ -6869,9 +7338,9 @@ } }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD", "peer": true }, @@ -6954,6 +7423,18 @@ "typescript": ">=4.3.0" } }, + "node_modules/typechain/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/typechain/node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -7004,6 +7485,20 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/typechain/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/typechain/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -7038,9 +7533,9 @@ "peer": true }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "devOptional": true, "license": "Apache-2.0", "peer": true, @@ -7064,9 +7559,9 @@ } }, "node_modules/uglify-js": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.0.tgz", - "integrity": "sha512-wNKHUY2hYYkf6oSFfhwwiHo4WCHzHmzcXsqXYTN9ja3iApYIFbb2U6ics9hBcYLHcYGQoAlwnZlTrf3oF+BL/Q==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, "license": "BSD-2-Clause", "optional": true, @@ -7079,9 +7574,9 @@ } }, "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "version": "5.28.5", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", + "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", "license": "MIT", "dependencies": { "@fastify/busboy": "^2.0.0" @@ -7091,9 +7586,9 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "license": "MIT" }, "node_modules/universalify": { @@ -7211,17 +7706,18 @@ } }, "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", - "peer": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { - "which": "bin/which" + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, "node_modules/widest-line": { @@ -7304,6 +7800,24 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -7398,6 +7912,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 9c36a4b8..0e9960ee 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "hardhat": "^2.22.18" }, "dependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^2.0.7" + "@nomicfoundation/hardhat-chai-matchers": "^2.0.7", + "glob": "^11.0.1" }, "scripts": { "format": "prettier --write \"test/**/*.js\"", diff --git a/script/Counter.s.sol b/script/Counter.s.sol index cdc1fe9a..e8f2cdb4 100644 --- a/script/Counter.s.sol +++ b/script/Counter.s.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import {Script, console} from "forge-std/Script.sol"; -import {Counter} from "../src/Counter.sol"; +import { Script, console } from "forge-std/Script.sol"; +import { Counter } from "../src/Counter.sol"; contract CounterScript is Script { - Counter public counter; + Counter public counter; - function setUp() public {} + function setUp() public { } - function run() public { - vm.startBroadcast(); + function run() public { + vm.startBroadcast(); - counter = new Counter(); + counter = new Counter(); - vm.stopBroadcast(); - } + vm.stopBroadcast(); + } } diff --git a/src/Counter.sol b/src/Counter.sol index aded7997..5242caa4 100644 --- a/src/Counter.sol +++ b/src/Counter.sol @@ -2,13 +2,13 @@ pragma solidity ^0.8.13; contract Counter { - uint256 public number; + uint256 public number; - function setNumber(uint256 newNumber) public { - number = newNumber; - } + function setNumber(uint256 newNumber) public { + number = newNumber; + } - function increment() public { - number++; - } + function increment() public { + number++; + } } diff --git a/submissions/Assignment1/README.md b/submissions/Assignment1/README.md new file mode 100644 index 00000000..cad7bad2 --- /dev/null +++ b/submissions/Assignment1/README.md @@ -0,0 +1,3 @@ +# Submissions for Assignment 3 + +Link to Counter Assignment1 [Here](../../contracts/counter_alex.sol) diff --git a/submissions/Assignment2/README.md b/submissions/Assignment2/README.md new file mode 100644 index 00000000..6f3a09c7 --- /dev/null +++ b/submissions/Assignment2/README.md @@ -0,0 +1,3 @@ +# Submissions for Assignment 3 +--- +--- \ No newline at end of file diff --git a/test/Counter.t.sol b/test/Counter.t.sol index 54b724f7..8c35c3ff 100644 --- a/test/Counter.t.sol +++ b/test/Counter.t.sol @@ -1,24 +1,225 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import {Test, console} from "forge-std/Test.sol"; -import {Counter} from "../src/Counter.sol"; +import { Test, console } from "forge-std/Test.sol"; +import { Counter } from "../contracts/with-foundry/Counter.sol"; contract CounterTest is Test { - Counter public counter; - - function setUp() public { - counter = new Counter(); - counter.setNumber(0); - } - - function test_Increment() public { - counter.increment(); - assertEq(counter.number(), 1); - } - - function testFuzz_SetNumber(uint256 x) public { - counter.setNumber(x); - assertEq(counter.number(), x); - } + Counter public counter; + address public owner; + address public nonOwner; + // set up the counter contract deployment + + function setUp() public { + // Set up addresses + owner = address(1); + nonOwner = address(2); + + console.log("Owner: ", owner); + console.log("Non-Owner: ", nonOwner); + + // Deploy contract as owner + vm.prank(owner); + counter = new Counter(); + } + // test increment function + + function test_Increment() public { + assertEq(counter.number(), 0); + vm.prank(owner); + counter.increment(); + assertEq(counter.number(), 1); + } + + // test decrement function + function test_Decrement() public { + assertEq(counter.number(), 0); + vm.prank(owner); + counter.add(5); + assertEq(counter.number(), 5); + vm.prank(owner); + counter.decrement(); + assertEq(counter.number(), 4); + } + + // test add by value function + function test_Add() public { + assertEq(counter.number(), 0); + vm.prank(owner); + counter.add(5); + assertEq(counter.number(), 5); + } + + // test substract by value function + function test_Sub() public { + assertEq(counter.number(), 0); + counter.setNumber(10); + vm.prank(owner); + counter.sub(5); + assertEq(counter.number(), 5); + } + + // test multiply by value function + function test_Mul() public { + assertEq(counter.number(), 0); + counter.setNumber(5); + vm.prank(owner); + counter.mul(5); + assertEq(counter.number(), 25); + } + + // test divide by value function + function test_Div() public { + assertEq(counter.number(), 0); + counter.setNumber(10); + vm.prank(owner); + counter.div(2); + assertEq(counter.number(), 5); + } + + // test if a number is even + function test_IsEven() public { + vm.startPrank(owner); + + // Test even numbers + assertTrue(counter.isEven(2), "2 should be even"); + assertTrue(counter.isEven(0), "0 should be even"); + assertTrue(counter.isEven(100), "100 should be even"); + + // Test that odd numbers return false + assertFalse(counter.isEven(1), "1 should not be even"); + assertFalse(counter.isEven(99), "99 should not be even"); + + vm.stopPrank(); + } + + // test if a number is odd + function testIsOdd() public { + vm.startPrank(owner); + + // Test odd numbers + assertTrue(counter.isOdd(1), "1 should be odd"); + assertTrue(counter.isOdd(99), "99 should be odd"); + assertTrue(counter.isOdd(777), "777 should be odd"); + + // Test that even numbers return false + assertFalse(counter.isOdd(2), "2 should not be odd"); + assertFalse(counter.isOdd(0), "0 should not be odd"); + + vm.stopPrank(); + } + + // test reset function + function test_Reset() public { + counter.setNumber(10); + vm.prank(owner); + counter.reset(); + assertEq(counter.number(), 0); + } + + // test get total function + function test_Get_Total() public { + assertEq(counter.number(), 0); + counter.setNumber(10); + vm.prank(owner); + counter.getTotal(); + assertEq(counter.number(), 10); + } + + // Testing for non-owner and expect revert with error message + // test increment function + function test_IncrementNonOwner() public { + assertEq(counter.number(), 0); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.increment(); + assertEq(counter.number(), 0); + } + + // test decrement function + function test_DecrementNonOwner() public { + assertEq(counter.number(), 0); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.add(5); + assertEq(counter.number(), 0); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.decrement(); + assertEq(counter.number(), 0); + } + + // test add by value function + function test_AddNonOwner() public { + assertEq(counter.number(), 0); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.add(5); + assertEq(counter.number(), 0); + } + + // test substract by value function + function test_SubNonOwner() public { + assertEq(counter.number(), 0); + counter.setNumber(10); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.sub(5); + assertEq(counter.number(), 10); + } + + // test multiply by value function + function test_MulNonOwner() public { + assertEq(counter.number(), 0); + counter.setNumber(5); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.mul(5); + assertEq(counter.number(), 5); + } + + // test divide by value function + function test_DivNonOwner() public { + assertEq(counter.number(), 0); + counter.setNumber(10); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.div(2); + assertEq(counter.number(), 10); + } + + // test if a number is even + function test_IsEvenNonOwner() public { + // Test even numbers + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.isEven(2); + } + + // test if a number is odd + function testIsOddNonOwner() public { + // Test odd numbers + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.isOdd(9); + } + + // test reset function + function test_ResetNonOwner() public { + counter.setNumber(10); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.reset(); + assertEq(counter.number(), 10); + } + + // // test get total function + function test_Get_TotalNonOwner() public { + assertEq(counter.number(), 0); + counter.setNumber(10); + vm.prank(nonOwner); + vm.expectRevert("Only owner can call this function"); + counter.getTotal(); + assertEq(counter.number(), 10); + } } diff --git a/test/CrowdFundingV2.t.sol b/test/CrowdFundingV2.t.sol new file mode 100644 index 00000000..dcb7b14c --- /dev/null +++ b/test/CrowdFundingV2.t.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +import {Test, console} from "forge-std/Test.sol"; +import {CrowdfundingV2} from "../contracts/chainlink-integration/CrowdFundingV2.sol"; +import {RewardToken} from "../contracts/with-foundry/RewardToken.sol"; +import {RewardNft} from "../contracts/with-foundry/RewardNft.sol"; +import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol"; +// import {AggregatorV3Interface} from "../lib/chainlink-local/lib/chainlink-brownie-contracts/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol"; + +contract CrowdfundingTest is Test { + // Crowdfunding contract state variables + CrowdfundingV2 public crowdfundingV2; + RewardToken public rewardtoken; + RewardNft public rewardnft; + uint256 public constant FUNDING_GOAL_IN_USD = 50000; + uint256 public constant NFT_THRESHOLD = 1000; + uint256 public totalFundsRaised; + bool public isFundingComplete; + uint256 constant REWARD_RATE = 100; + uint256 sepoliaFork; + + // Addresses for testing + address crowdfundingV2Addr = address(this); + address owner = vm.addr(1); + address addr2 = vm.addr(2); + address addr3 = vm.addr(3); + address addr4 = vm.addr(4); + address addr5 = vm.addr(5); + AggregatorV3Interface priceFeed; + + event ContributionReceived(address indexed contributor, uint256 amount); + event NFTRewardSent(address indexed receiver, uint256 Id); + event TokenRewardSent(address indexed receiver, uint256 Amount); + event FundsWithdrawn(address indexed receiver, uint256 Amount); + + address public constant ETH_USD_ADDR = 0x694AA1769357215DE4FAC081bf1f309aDC325306; + + function setUp() public { + // Create the Sepolia fork + sepoliaFork = vm.createFork("UPDATE-YOUR-RPC-URL-HERE-NOT-SAFE-FOR-GITHUB"); + vm.selectFork(sepoliaFork); + + // Set the fork to a specific block before any other operations + vm.rollFork(7887153); + + // deploy contracts with the owner address + vm.startPrank(owner); + + rewardtoken = new RewardToken(); + rewardnft = new RewardNft("RewardNft", "RNFT", "ipfs://"); + + // Transfer Reward tokens from owner to the contract + crowdfundingV2 = new CrowdfundingV2(REWARD_RATE, address(rewardtoken), address(rewardnft)); + + rewardtoken.transfer(address(this), 5000); + vm.stopPrank(); + + vm.deal(addr2, 100 ether); + vm.deal(addr3, 100 ether); + vm.deal(addr4, 100 ether); + vm.deal(addr5, 100 ether); + } + + // ******DEPLOYMENT******// + // Test state variables at deployment + // Should set the correct CrowdFunding contract owner + function test_setContractOwner() public view { + assertEq(crowdfundingV2.Owner(), owner); + } + + // Should set the correct crowd Token contract owner + function test_setTokenContractOwner() public view { + assertEq(rewardtoken.owner(), owner); + } + + // should transfer the correct amount of reward tokens to the crowdfunding contract + function test_RewardTokenBalanceOfCrowdfundingOnDeployment() public view { + uint256 contractBal1 = rewardtoken.balanceOf(crowdfundingV2Addr); + assertEq(contractBal1, 5000); + + uint256 ownerRewardTokenBalance = rewardtoken.balanceOf(owner); + assertEq(ownerRewardTokenBalance, 0); + } + + // Should set the correct rewardNFT contract owner + function test_setNFTContractOwner() public view { + assertEq(rewardnft.owner(), owner); + } + + // Should set the correct funding goal + function test_setCorrectFundingGoal() public view { + assertEq(crowdfundingV2.FUNDING_GOAL_IN_USD(), FUNDING_GOAL_IN_USD); + } + + // Should set the correct token reward rate + function test_setTokenReward() public view { + assertEq(crowdfundingV2.tokenRewardRate(), REWARD_RATE); + } + + // Should set the correct NFT threshold + function test_set_NFT_Threshold() public view { + assertEq(crowdfundingV2.NFT_THRESHOLD(), NFT_THRESHOLD); + } + + // Should determine that totalFundsRaised is zero initially + function test_total_funds_raised() public view { + assertEq(crowdfundingV2.totalFundsRaised(), 0); + } + + // Should set isFundingComplete to false initially + function test_is_funding_complete() public view { + assertEq(crowdfundingV2.isFundingComplete(), false); + } + + function test_getLatestPrice() public view { + int256 ethUSDPrice = crowdfundingV2.getLatestPrice(); + console.log("eth price = ", ethUSDPrice); + } +} diff --git a/test/Crowdfunding.t.sol b/test/Crowdfunding.t.sol new file mode 100644 index 00000000..c1a02f43 --- /dev/null +++ b/test/Crowdfunding.t.sol @@ -0,0 +1,462 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +import {Test, console} from "forge-std/Test.sol"; +// import {Crowdfunding} from "../src/Crowdfunding.sol"; +import {Crowdfunding} from "../contracts/with-foundry/Crowdfunding.sol"; +import {RewardToken} from "../contracts/with-foundry/RewardToken.sol"; +import {RewardNft} from "../contracts/with-foundry/RewardNft.sol"; + +contract CrowdfundingTest is Test { + // Crowdfunding contract state variables + Crowdfunding public crowdfunding; + RewardToken public rewardtoken; + RewardNft public rewardnft; + uint public constant FUNDING_GOAL = 50 ether; + uint public constant NFT_THRESHOLD = 5 ether; + uint256 public totalFundsRaised; + bool public isFundingComplete; + uint256 constant REWARD_RATE = 100; + + // Addresses for testing + address crowdfundingAddr = address(this); + address owner = vm.addr(1); + address addr2 = vm.addr(2); + address addr3 = vm.addr(3); + address addr4 = vm.addr(4); + address addr5 = vm.addr(5); + + receive() external payable {} + + event ContributionReceived(address indexed contributor, uint256 amount); + event NFTRewardSent(address indexed receiver, uint256 Id); + event TokenRewardSent(address indexed receiver, uint256 Amount); + event FundsWithdrawn(address indexed receiver, uint256 Amount); + + function calculateTokenReward(uint256 ethContribution) public view returns (uint256) { + return (ethContribution * crowdfunding.tokenRewardRate()) / 1 ether; + } + + function setUp() public { + vm.startPrank(owner); + + rewardtoken = new RewardToken(); + + rewardnft = new RewardNft("RewardNft", "RNFT", "ipfs://"); + + crowdfunding = new Crowdfunding(REWARD_RATE, address(rewardtoken), address(rewardnft)); + // Transfer Reward tokens from owner to the contract + rewardtoken.transfer(address(crowdfunding), 5000); + vm.stopPrank(); + + vm.deal(addr2, 100 ether); + vm.deal(addr3, 100 ether); + vm.deal(addr4, 100 ether); + vm.deal(addr5, 100 ether); + } + + // ******DEPLOYMENT******// + // Test state variables at deployment + // Should set the correct CrowdFunding contract owner + function test_setContractOwner() public view { + assertEq(crowdfunding.Owner(), owner); + } + // Should set the correct crowd Token contract owner + function test_setTokenContractOwner() public view { + assertEq(rewardtoken.owner(), owner); + } + + // should transfer the correct amount of reward tokens to the crowdfunding contract + function test_RewardTokenBalanceOfCrowdfundingOnDeployment() public view { + uint256 contractBal1 = rewardtoken.balanceOf(address(crowdfunding)); + assertEq(contractBal1, 5000); + + uint256 ownerRewardTokenBalance = rewardtoken.balanceOf(owner); + assertEq(ownerRewardTokenBalance, 0); + } + + // Should set the correct rewardNFT contract owner + function test_setNFTContractOwner() public view { + assertEq(rewardnft.owner(), owner); + } + + // Should set the correct funding goal + function test_setCorrectFundingGoal() public view { + assertEq(crowdfunding.FUNDING_GOAL(), FUNDING_GOAL); + } + + // Should set the correct token reward rate + function test_setTokenReward() public view { + assertEq(crowdfunding.tokenRewardRate(), REWARD_RATE); + } + + // Should set the correct NFT threshold + function test_set_NFT_Threshold() public view { + assertEq(crowdfunding.NFT_THRESHOLD(), NFT_THRESHOLD); + } + + // Should determine that totalFundsRaised is zero initially + function test_total_funds_raised() public view { + assertEq(crowdfunding.totalFundsRaised(), 0); + } + + // Should set isFundingComplete to false initially + function test_is_funding_complete() public view { + assertEq(crowdfunding.isFundingComplete(), false); + } + + // ********* TRANSACTIONS *********// + // Allows Eth contribution from user + function test_allow_eth_contribution() public { + uint256 contributionAmount = 10 ether; + uint256 addr2InitialEthBal = addr2.balance; // address 2 initial balance + + uint256 initialEthBalanceCrowdFunding = address(crowdfunding).balance; // initial balance of crowdfunding contract + + uint256 contractRewardTokenBal = rewardtoken.balanceOf(address(crowdfunding)); + assertEq(contractRewardTokenBal, 5000); + + uint256 ownerRewardTokenBalance = rewardtoken.balanceOf(owner); + assertEq(ownerRewardTokenBalance, 0); + + assertEq(initialEthBalanceCrowdFunding, 0); + assertEq(addr2InitialEthBal, 100 ether); + // Perform the contribution + vm.prank(addr2); + crowdfunding.contribute{value: contributionAmount}(); + + uint256 addr2EthBalAfterContr = addr2.balance; // address 2 balance after contribution + uint256 crowdfundingBalAfterContr = address(crowdfunding).balance; // crowdfunding balance after contribution + + assertEq(addr2EthBalAfterContr, addr2InitialEthBal - contributionAmount); + assertEq(crowdfundingBalAfterContr, initialEthBalanceCrowdFunding + contributionAmount); + } + + // determine that the token reward amount is based on contribution + function test_calculate_token_reward_amount() public view { + // first calculate the token reward for 2 ether + uint256 rewardAmount1 = calculateTokenReward(2 ether); + assertEq(rewardAmount1, 200); + + // Calculate the token reward for 5 ether + uint256 rewardAmount2 = calculateTokenReward(5 ether); + assertEq(rewardAmount2, 500); + + // Calculate the token reward for 10 ether + uint256 rewardAmount3 = calculateTokenReward(10 ether); + assertEq(rewardAmount3, 1000); + } + + // Should send the correct token reward to the contributor + function test_user_receive_accurate_token_reward_on_contribution() public { + uint256 contributionAmount = 4 ether; + uint256 addr3InitialEthBal = addr3.balance; // address 3 initial balance + uint256 addr3InitialTokenBal = rewardtoken.balanceOf(addr3); // address 3 initial token balance + uint256 rewardAmount = calculateTokenReward(4 ether); + + uint256 initialEthBalanceCrowdFunding = address(crowdfunding).balance; // initial balance of crowdfunding contract + + uint256 contractRewardTokenBal = rewardtoken.balanceOf(address(crowdfunding)); + assertEq(contractRewardTokenBal, 5000); + + uint256 ownerRewardTokenBalance = rewardtoken.balanceOf(owner); + assertEq(ownerRewardTokenBalance, 0); + + assertEq(initialEthBalanceCrowdFunding, 0); + assertEq(addr3InitialEthBal, 100 ether); + + // Perform the contribution with address 3 + vm.prank(addr3); + crowdfunding.contribute{value: contributionAmount}(); + + uint256 addr3EthBalAfterContr = addr3.balance; // address 3 balance after contribution + uint256 addr3TokenBalAfterContr = rewardtoken.balanceOf(addr3); // address 3 initial token balance + uint256 crowdfundingBalAfterContrtion = address(crowdfunding).balance; // crowdfunding balance after contribution + + assertEq(addr3TokenBalAfterContr, rewardAmount); + assertEq(addr3EthBalAfterContr, addr3InitialEthBal - contributionAmount); + assertEq(crowdfundingBalAfterContrtion, initialEthBalanceCrowdFunding + contributionAmount); + } + + // Should send the correct token reward and nft to the contributor + function test_user_receive_accurate_token_reward_and_nft_on_contribution() public { + uint256 contributionAmount = 7 ether; + uint256 addr3InitialEthBal = addr3.balance; // address 3 initial balance + uint256 addr3InitialTokenBal = rewardtoken.balanceOf(addr3); // address 3 initial token balance + uint256 addr3InitialNftBal = rewardnft.balanceOf(addr3); // address 3 initial token balance + uint256 rewardAmount = calculateTokenReward(7 ether); + + uint256 initialEthBalanceCrowdFunding = address(crowdfunding).balance; // initial balance of crowdfunding contract + + uint256 contractRewardTokenBal = rewardtoken.balanceOf(address(crowdfunding)); + assertEq(contractRewardTokenBal, 5000); + + uint256 ownerRewardTokenBalance = rewardtoken.balanceOf(owner); + assertEq(ownerRewardTokenBalance, 0); + + assertEq(initialEthBalanceCrowdFunding, 0); + assertEq(addr3InitialEthBal, 100 ether); + + // Perform the contribution with address 3 + vm.prank(addr3); + crowdfunding.contribute{value: contributionAmount}(); + + uint256 addr3EthBalAfterContr = addr3.balance; // address 3 balance after contribution + uint256 addr3TokenBalAfterContr = rewardtoken.balanceOf(addr3); // address 3 initial token balance + uint256 addr3NftBalAfterContr = rewardnft.balanceOf(addr3); // address 3 initial token balance + uint256 crowdfundingBalAfterContrtion = address(crowdfunding).balance; // crowdfunding balance after contribution + + assertEq(addr3TokenBalAfterContr, rewardAmount); + assertEq(addr3NftBalAfterContr, 1); + assertEq(addr3EthBalAfterContr, addr3InitialEthBal - contributionAmount); + assertEq(crowdfundingBalAfterContrtion, initialEthBalanceCrowdFunding + contributionAmount); + } + + // should not mint NFT below threshold + function test_not_mint_nft_below_threshold() public { + vm.prank(addr2); + crowdfunding.contribute{value: 3 ether}(); + assertEq(rewardnft.balanceOf(addr2), 0); + + assertEq(crowdfunding.hasReceivedNFT(addr2), false); + } + + // should mint NFT + function test_should_mint_nft() public { + vm.prank(addr2); + crowdfunding.contribute{value: 10 ether}(); + assertEq(rewardnft.balanceOf(addr2), 1); + assertEq(crowdfunding.hasReceivedNFT(addr2), true); + } + + // should mint NFT for cummulative contributions + function test_mint_for_cummulative() public { + vm.prank(addr2); + crowdfunding.contribute{value: 2 ether}(); + assertEq(rewardnft.balanceOf(addr2), 0); + + vm.prank(addr2); + crowdfunding.contribute{value: 4 ether}(); + assertEq(rewardnft.balanceOf(addr2), 1); + } + + // should not mint additional NFT + function test_should_not_mint_additional_nft() public { + vm.prank(addr2); + crowdfunding.contribute{value: 8 ether}(); + assertEq(rewardnft.balanceOf(addr2), 1); + + vm.prank(addr2); + crowdfunding.contribute{value: 10 ether}(); + assertEq(rewardnft.balanceOf(addr2), 1); + } + + // should track individual contributions + function test_track_individual_contributions() public { + vm.prank(addr2); + crowdfunding.contribute{value: 10 ether}(); + assertEq(crowdfunding.getContribution(addr2), 10 ether); + + vm.prank(addr3); + crowdfunding.contribute{value: 20 ether}(); + assertEq(crowdfunding.getContribution(addr3), 20 ether); + } + + // should track multiple contributions + function test_track_multiple_contributions() public { + vm.prank(addr2); + crowdfunding.contribute{value: 10 ether}(); + assertEq(crowdfunding.getContribution(addr2), 10 ether); + + vm.prank(addr2); + crowdfunding.contribute{value: 20 ether}(); + assertEq(crowdfunding.getContribution(addr2), 30 ether); + } + + // should track funding progress + function test_track_funding_progress() public { + vm.prank(addr2); + crowdfunding.contribute{value: 40 ether}(); + assertEq(crowdfunding.totalFundsRaised(), 40 ether); + assertEq(crowdfunding.isFundingComplete(), false); + + vm.prank(addr2); + crowdfunding.contribute{value: 10 ether}(); + assertEq(crowdfunding.totalFundsRaised(), 50 ether); + assertEq(crowdfunding.isFundingComplete(), true); + } + + // should allow owner to withdraw funds + function test_allow_owner_to_withdraw() public { + uint256 initialOwnerBalance = owner.balance; + assertEq(owner.balance, 0); + + vm.prank(addr2); + crowdfunding.contribute{value: FUNDING_GOAL}(); + assertEq(addr2.balance, 50 ether); + + assertEq(crowdfunding.totalFundsRaised(), FUNDING_GOAL); + assertEq(crowdfunding.contributions(addr2), 50 ether); + + vm.prank(owner); + crowdfunding.withdrawFunds(); + assertEq(owner.balance, initialOwnerBalance + FUNDING_GOAL); + } + + // should not allow withdrawal if funding goal not reached + function test_reject_withdrawal_if_funding_not_reached() public { + vm.prank(addr2); + crowdfunding.contribute{value: 20 ether}(); + assertEq(addr2.balance, 80 ether); + + vm.expectRevert("Funding goal not yet reached"); + + vm.prank(owner); + crowdfunding.withdrawFunds(); + } + + // should not allow non-owner to withdraw funds + function test_withdrawal_for_nonOwner() public { + vm.prank(addr2); + crowdfunding.contribute{value: 50 ether}(); + vm.expectRevert("Only project owner can withdraw"); + vm.prank(addr2); + crowdfunding.withdrawFunds(); + } + + function test_correctly_track_individual_contributions() public { + vm.prank(addr2); + crowdfunding.contribute{value: 12 ether}(); + + vm.prank(addr3); + crowdfunding.contribute{value: 12 ether}(); + + // vm.prank(addr5); + // crowdfunding.contribute{value: 12 ether}(); + + assertEq(crowdfunding.getContribution(addr2), 12 ether); + assertEq(crowdfunding.getContribution(addr3), 12 ether); + // assertEq(crowdfunding.getContribution(addr5), 12 ether); + } + + function test_contribution_amount_for_repeat_contributions() public { + vm.prank(addr2); + crowdfunding.contribute{value: 12 ether}(); + + vm.prank(addr2); + crowdfunding.contribute{value: 12 ether}(); + + assertEq(crowdfunding.getContribution(addr2), 24 ether); + } + + // validations + function test_should_reject_zero_contribution() public { + vm.expectRevert("Contribution must be greater than 0"); + vm.prank(addr2); + crowdfunding.contribute{value: 0 ether}(); + } + + function test_reject_contributions_after_funding_goal_is_reached() public { + vm.prank(addr2); + crowdfunding.contribute{value: 50 ether}(); + + vm.expectRevert("Funding goal already reached"); + vm.prank(addr3); + crowdfunding.contribute{value: 0.00001 ether}(); + + vm.prank(owner); + crowdfunding.withdrawFunds(); + } + + // should refund excess contribution to the contributor + function test_refund_excess_contribution() public { + // First contribute most of the funding goal + uint256 initialContribution = 45 ether; + vm.prank(addr2); + crowdfunding.contribute{value: initialContribution}(); + + // Verify initial contribution state + assertEq(crowdfunding.totalFundsRaised(), initialContribution); + + // Calculate remaining amount needed and prepare second contribution + uint256 secondContribution = 10 ether; + uint256 remainingToGoal = FUNDING_GOAL - initialContribution; // Should be 5 ether + uint256 expectedRefund = secondContribution - remainingToGoal; // Should be 5 ether + + // Ascertain that addr3's balance is unchanged + uint256 addr3BalanceBefore = addr3.balance; + assertEq(addr3BalanceBefore, 100 ether); + + // Make contribution that should trigger refund + vm.prank(addr3); + crowdfunding.contribute{value: secondContribution}(); + + // Verify final states + assertEq(crowdfunding.totalFundsRaised(), FUNDING_GOAL); + assertEq(crowdfunding.isFundingComplete(), true); + assertEq(crowdfunding.getContribution(addr3), remainingToGoal); + uint256 crowdfundinBal2 = address(crowdfunding).balance; + + assertEq(crowdfundinBal2, FUNDING_GOAL); + + // Verify addr3 received the correct refund + // Final balance should be: initial balance - contribution + refund + uint256 expectedBalance = addr3BalanceBefore - secondContribution + expectedRefund; + assertEq(addr3.balance, expectedBalance); + } + + // ********* EVENTS *********// + // Should emit FundsWithdrawn event + function test_emit_funds_withdrawn_event() public { + // First reach the funding goal + vm.prank(addr2); + crowdfunding.contribute{value: FUNDING_GOAL}(); + + // Set up the event check + vm.expectEmit(true, true, false, true, address(crowdfunding)); + + emit FundsWithdrawn(owner, FUNDING_GOAL); // emit the expected arguments + + vm.prank(owner); // Prank the owner to withdraw funds + crowdfunding.withdrawFunds(); + } + // Should emit TokenRewardSent event + function test_emit_token_reward_sent_event() public { + // Calculate expected tokens based on reward rate + uint256 expectedTokens = (2 ether * REWARD_RATE) / 1 ether; + + // Set up the event check + vm.expectEmit(true, true, false, true, address(crowdfunding)); + + // Emit the expected event with expected arguments + emit TokenRewardSent(addr2, expectedTokens); + + // Make the contribution that should trigger the token reward + vm.prank(addr2); + crowdfunding.contribute{value: 2 ether}(); + } + // Should emit ContributionReceived event + function test_emit_contribution_received_event() public { + vm.expectEmit(true, true, false, true, address(crowdfunding)); + + // Emit the expected event with the expected arguments + emit ContributionReceived(addr2, 20 ether); + + // Perform the action that should emit the event + vm.prank(addr2); + crowdfunding.contribute{value: 20 ether}(); + } + + // Should emit NFTRewardSent event + function test_emit_nft_reward_sent_event() public { + // Set up the event check - we want to verify the NFTRewardSent event + vm.expectEmit(true, true, true, true, address(crowdfunding)); + + // Emit the expected event with expected arguments + emit NFTRewardSent(addr2, 1); // First NFT should have ID 1 + + // Make the contribution that should trigger the NFT reward + vm.prank(addr2); + crowdfunding.contribute{value: NFT_THRESHOLD}(); + } +} diff --git a/test/Payable.t.sol b/test/Payable.t.sol new file mode 100644 index 00000000..f77108f5 --- /dev/null +++ b/test/Payable.t.sol @@ -0,0 +1,70 @@ +// // SPDX-License-Identifier: MIT +// pragma solidity ^0.8.24; + +// import {Test, console} from "forge-std/Test.sol"; +// import {Payable} from "../src/Payable.sol"; + +// contract PayableTest is Test { +// Payable public payableContract; +// address public owner; +// address public user1; +// address public user2; + +// function setUp() public { +// owner = vm.addr(1); +// user1 = vm.addr(2); +// user2 = vm.addr(3); + +// console.log("Owner: ", owner); +// console.log("User 1: ", user1); +// console.log("User 2: ", user2); + +// vm.prank(owner); +// payableContract = new Payable(); +// } + +// function test_Deposit() public { +// vm.deal(user1, 1 ether); // Give user1 some ETH +// vm.startPrank(user1); + +// payableContract.deposit{value: 0.1 ether}(0.1 ether); + +// assertEq(payableContract.getInvestment(user1), 0.1 ether); +// assertEq(payableContract.getContractBalance(), 0.1 ether); + +// vm.stopPrank(); +// } + +// function test_GetInvestment() public { +// vm.deal(user1, 1 ether); // Give user1 some ETH +// vm.startPrank(user1); + +// payableContract.deposit{value: 0.1 ether}(0.1 ether); + +// assertEq(payableContract.getInvestment(user1), 0.1 ether); + +// vm.stopPrank(); +// } + +// function test_GetContractBalance() public { +// vm.deal(user1, 1 ether); // Give user1 some ETH +// vm.startPrank(user1); + +// payableContract.deposit{value: 0.1 ether}(0.1 ether); + +// assertEq(payableContract.getContractBalance(), 0.1 ether); + +// vm.stopPrank(); +// } + +// function test_GetMyEthBalance() public { +// vm.deal(user1, 1 ether); // Give user1 some ETH +// vm.startPrank(user1); + +// payableContract.deposit{value: 0.1 ether}(0.1 ether); + +// assertEq(payableContract.getMyEthBalance(), 0.9 ether); + +// vm.stopPrank(); +// } +// }