From 2fae2d5f71b58e58521b12838948f96a8b927901 Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Wed, 31 Jan 2024 14:32:56 +0100 Subject: [PATCH 1/5] fix: comments --- contracts/DistributionCreator.sol | 11 ++++++----- contracts/Distributor.sol | 6 +++--- contracts/struct/CampaignParameters.sol | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 contracts/struct/CampaignParameters.sol diff --git a/contracts/DistributionCreator.sol b/contracts/DistributionCreator.sol index dfe83d2..196360b 100644 --- a/contracts/DistributionCreator.sol +++ b/contracts/DistributionCreator.sol @@ -43,6 +43,7 @@ import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { IUniswapV3Pool } from "./interfaces/external/uniswap/IUniswapV3Pool.sol"; import "./utils/UUPSHelper.sol"; +import { CampaignParameters } from "./struct/CampaignParameters.sol"; import { DistributionParameters } from "./struct/DistributionParameters.sol"; import { RewardTokenAmounts } from "./struct/RewardTokenAmounts.sol"; @@ -61,10 +62,8 @@ struct CampaignParameters { /// @title DistributionCreator /// @author Angle Labs, Inc. -/// @notice Manages the distribution of rewards across different pools with concentrated liquidity (like on Uniswap V3) +/// @notice Manages the distribution of rewards through the Merkl system /// @dev This contract is mostly a helper for APIs built on top of Merkl -/// @dev People depositing rewards must have signed a `message` with the conditions for using the -/// product //solhint-disable contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { using SafeERC20 for IERC20; @@ -81,7 +80,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice `Core` contract handling access control ICore public core; - /// @notice User contract for distributing rewards + /// @notice Contract distributing rewards to users address public distributor; /// @notice Address to which fees are forwarded @@ -96,7 +95,8 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice Hash of the message that needs to be signed bytes32 public messageHash; - /// @notice List of all rewards ever distributed or to be distributed in the contract + /// @notice List of all rewards distributed in the contract on campaigns created before mid Feb 2024 + /// for concentrated liquidity pools /// @dev An attacker could try to populate this list. It shouldn't be an issue as only view functions /// iterate on it DistributionParameters[] public distributionList; @@ -132,6 +132,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice Maps a campaignId to the ID of the campaign in the campaign list + 1 mapping(bytes32 => uint256) internal _campaignLookup; + /// @notice Maps a campaign type to the fees for this specific campaign mapping(uint32 => uint256) public campaignSpecificFees; /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/contracts/Distributor.sol b/contracts/Distributor.sol index 25c5bcf..1599e54 100644 --- a/contracts/Distributor.sol +++ b/contracts/Distributor.sol @@ -290,20 +290,20 @@ contract Distributor is UUPSHelper { } /// @notice Sets the dispute period after which a tree update becomes effective - function setDisputePeriod(uint48 _disputePeriod) external onlyGovernorOrGuardian { + function setDisputePeriod(uint48 _disputePeriod) external onlyGovernor { disputePeriod = uint48(_disputePeriod); emit DisputePeriodUpdated(_disputePeriod); } /// @notice Sets the token used as a caution during disputes - function setDisputeToken(IERC20 _disputeToken) external onlyGovernorOrGuardian { + function setDisputeToken(IERC20 _disputeToken) external onlyGovernor { if (disputer != address(0)) revert UnresolvedDispute(); disputeToken = _disputeToken; emit DisputeTokenUpdated(address(_disputeToken)); } /// @notice Sets the amount of `disputeToken` used as a caution during disputes - function setDisputeAmount(uint256 _disputeAmount) external onlyGovernorOrGuardian { + function setDisputeAmount(uint256 _disputeAmount) external onlyGovernor { if (disputer != address(0)) revert UnresolvedDispute(); disputeAmount = _disputeAmount; emit DisputeAmountUpdated(_disputeAmount); diff --git a/contracts/struct/CampaignParameters.sol b/contracts/struct/CampaignParameters.sol new file mode 100644 index 0000000..7423f7d --- /dev/null +++ b/contracts/struct/CampaignParameters.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity ^0.8.17; + +struct CampaignParameters { + // Populated once created + bytes32 campaignId; + // Chosen by campaign creator + address creator; + address rewardToken; + uint256 amount; + uint32 campaignType; + uint32 startTimestamp; + uint32 duration; // in seconds, has to be a multiple of EPOCH + bytes campaignData; +} From 0313109105476a8a782e6ece2d607398ee4f335f Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Wed, 31 Jan 2024 15:24:48 +0100 Subject: [PATCH 2/5] fix updates --- .npmrc | 1 + contracts/DistributionCreator.sol | 117 +++---- .../deprecated/OldDistributionCreator.sol | 307 +++++++++++++++--- contracts/deprecated/OldDistributor.sol | 70 ++-- package.json | 2 +- scripts/checkUpgradeability.ts | 8 + ...butor.ts => upgradeDistributionCreator.ts} | 15 +- 7 files changed, 368 insertions(+), 152 deletions(-) create mode 100644 .npmrc rename scripts/mainnet-fork/{migrationAngleDistributor.ts => upgradeDistributionCreator.ts} (93%) diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..af66bba --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +@angleprotocol:registry=https://npm.pkg.github.com diff --git a/contracts/DistributionCreator.sol b/contracts/DistributionCreator.sol index 196360b..88266b0 100644 --- a/contracts/DistributionCreator.sol +++ b/contracts/DistributionCreator.sol @@ -47,23 +47,14 @@ import { CampaignParameters } from "./struct/CampaignParameters.sol"; import { DistributionParameters } from "./struct/DistributionParameters.sol"; import { RewardTokenAmounts } from "./struct/RewardTokenAmounts.sol"; -struct CampaignParameters { - // Populated once created - bytes32 campaignId; - // Chosen by campaign creator - address creator; - address rewardToken; - uint256 amount; - uint32 campaignType; - uint32 startTimestamp; - uint32 duration; - bytes campaignData; -} - /// @title DistributionCreator /// @author Angle Labs, Inc. /// @notice Manages the distribution of rewards through the Merkl system /// @dev This contract is mostly a helper for APIs built on top of Merkl +/// @dev This contract is an upgraded version and distinguishes two types of different rewards: +/// - distributions: type of campaign for concentrated liquidity pools created before Feb 15 2024, +/// now deprecated +/// - campaigns: the new more global name to describe any reward program on top of Merkl //solhint-disable contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { using SafeERC20 for IERC20; @@ -86,10 +77,10 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice Address to which fees are forwarded address public feeRecipient; - /// @notice Value (in base 10**9) of the fees taken when creating a distribution for a pool + /// @notice Value (in base 10**9) of the fees taken when creating a campaign uint256 public defaultFees; - /// @notice Message that needs to be acknowledged by users creating a distribution + /// @notice Message that needs to be acknowledged by users creating a campaign string public message; /// @notice Hash of the message that needs to be signed @@ -97,8 +88,6 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice List of all rewards distributed in the contract on campaigns created before mid Feb 2024 /// for concentrated liquidity pools - /// @dev An attacker could try to populate this list. It shouldn't be an issue as only view functions - /// iterate on it DistributionParameters[] public distributionList; /// @notice Maps an address to its fee rebate @@ -108,7 +97,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// on pools with whitelisted tokens mapping(address => uint256) public isWhitelistedToken; - /// @deprecated, kept for storage compatibility + /// @notice Deprecated, kept for storage compatibility mapping(address => uint256) public _nonces; /// @notice Maps an address to the last valid hash signed @@ -200,46 +189,12 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { USER FACING FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ - /// @notice Creates a `distribution` to incentivize a given pool for a specific period of time - /// @return distributionAmount How many reward tokens are actually taken into consideration in the contract - /// @dev If the address specified as a UniV3 pool is not effectively a pool, it will not be handled by the - /// distribution script and rewards may be lost - /// @dev Reward tokens sent as part of distributions must have been whitelisted before and amounts - /// sent should be bigger than a minimum amount specific to each token - /// @dev The `positionWrappers` specified in the `distribution` struct need to be supported by the script - /// List of supported `positionWrappers` can be found in the docs. - /// @dev If the pool incentivized contains one whitelisted token, then no fees are taken on the rewards - /// @dev This function reverts if the sender has not signed the message `messageHash` once through one of - /// the functions enabling to sign - function createDistribution( - DistributionParameters memory distribution - ) external nonReentrant hasSigned returns (uint256 distributionAmount) { - return _createDistribution(distribution); - } - - /// @notice Same as the function above but for multiple distributions at once - /// @return List of all the distribution amounts actually deposited for each `distribution` in the `distributions` list - function createDistributions( - DistributionParameters[] memory distributions - ) external nonReentrant hasSigned returns (uint256[] memory) { - uint256 distributionsLength = distributions.length; - uint256[] memory distributionAmounts = new uint256[](distributionsLength); - for (uint256 i; i < distributionsLength; ) { - distributionAmounts[i] = _createDistribution(distributions[i]); - unchecked { - ++i; - } - } - return distributionAmounts; - } - /// @notice Creates a `campaign` to incentivize a given pool for a specific period of time /// @return campaignAmount How many reward tokens are actually taken into consideration in the contract /// @dev If the campaign is badly specified, it will not be handled by the campaign script and rewards may be lost /// @dev Reward tokens sent as part of campaigns must have been whitelisted before and amounts /// sent should be bigger than a minimum amount specific to each token - /// @dev This function reverts if the sender has not signed the message `messageHash` once through one of - /// the functions enabling to sign + /// @dev This function reverts if the sender has not accepted the terms and conditions function createCampaign(CampaignParameters memory campaign) external nonReentrant hasSigned returns (bytes32) { return _createCampaign(campaign); } @@ -261,6 +216,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { } /// @notice Allows a user to accept the conditions without signing the message + /// @dev Users may either call `acceptConditions` here or `sign` the message function acceptConditions() external { userSignatureWhitelist[msg.sender] = 1; } @@ -273,15 +229,6 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { _sign(signature); } - /// @notice Combines signing the message and creating a distribution - function signAndCreateDistribution( - DistributionParameters memory distribution, - bytes calldata signature - ) external returns (uint256 distributionAmount) { - _sign(signature); - return _createDistribution(distribution); - } - /// @notice Combines signing the message and creating a campaign function signAndCreateCampaign( CampaignParameters memory campaign, @@ -291,6 +238,28 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { return _createCampaign(campaign); } + /// @notice Creates a `distribution` to incentivize a given pool for a specific period of time + function createDistribution( + DistributionParameters memory distribution + ) external nonReentrant hasSigned returns (uint256 distributionAmount) { + return _createDistribution(distribution); + } + + /// @notice Same as the function above but for multiple distributions at once + function createDistributions( + DistributionParameters[] memory distributions + ) external nonReentrant hasSigned returns (uint256[] memory) { + uint256 distributionsLength = distributions.length; + uint256[] memory distributionAmounts = new uint256[](distributionsLength); + for (uint256 i; i < distributionsLength; ) { + distributionAmounts[i] = _createDistribution(distributions[i]); + unchecked { + ++i; + } + } + return distributionAmounts; + } + /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GETTERS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ @@ -348,7 +317,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { return _getValidRewardTokens(skip, first); } - /// @notice Similar to `getCampaignsBetween(uint256 epochStart, uint256 epochEnd)` with additional parameters to prevent out of gas error + /// @notice Gets all the campaigns which were live at some point between `start` and `end` timestamp /// @param skip Disregard distibutions with a global index lower than `skip` /// @param first Limit the length of the returned array to `first` /// @return searchCampaigns Eligible campaigns @@ -364,7 +333,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { return _getCampaignsBetween(start, end, skip, first); } - /// @notice Similar to `getDistributionsBetweenEpochs(uint256 epochStart, uint256 epochEnd)` with additional parameters to prevent out of gas error + /// @notice Gets all the distributions which were live at some point between `start` and `end` timestamp /// @param skip Disregard distibutions with a global index lower than `skip` /// @param first Limit the length of the returned array to `first` /// @return searchDistributions Eligible distributions @@ -475,7 +444,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { uint256 rewardTokenMinAmount = rewardTokenMinAmounts[campaign.rewardToken]; // if epoch parameters lead to a past campaign if (campaign.startTimestamp < block.timestamp) revert CampaignSouldStartInFuture(); - // if the distribution doesn't last at least one second + // if the campaign doesn't last at least one second if (campaign.duration == 0) revert CampaignDurationIsZero(); // if the reward token is not whitelisted as an incentive token if (rewardTokenMinAmount == 0) revert CampaignRewardTokenNotWhitelisted(); @@ -502,12 +471,12 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice Converts the deprecated distribution type into a campaign function _createDistribution(DistributionParameters memory distribution) internal returns (uint256) { - address[] memory whitelist = new address[](distribution.wrapperTypes.length); - address[] memory blacklist = new address[](distribution.wrapperTypes.length); + uint256 wrapperLength = distribution.wrapperTypes.length; + address[] memory whitelist = new address[](wrapperLength); + address[] memory blacklist = new address[](wrapperLength); uint256 whitelistLength; uint256 blacklistLength; - - for (uint256 k = 0; k < distribution.wrapperTypes.length; k++) { + for (uint256 k = 0; k < wrapperLength; k++) { if (distribution.wrapperTypes[k] == 0) { whitelist[whitelistLength] = (distribution.positionWrappers[k]); whitelistLength += 1; @@ -537,11 +506,11 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { distribution.propFees, // eg. 6000 distribution.propToken0, // eg. 3000 distribution.propToken1, // eg. 1000 - distribution.isOutOfRangeIncentivized, // eg. false + distribution.isOutOfRangeIncentivized, // eg. 0 distribution.boostingAddress, // eg. NULL_ADDRESS distribution.boostedReward, // eg. 0 whitelist, // eg. [] - blacklist, // blacklist + blacklist, // eg. [] "0x" ) }) @@ -585,8 +554,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { return (epoch / HOUR) * HOUR; } - /// @notice Gets the list of all the campaigns for `uniV3Pool` that have been active between `epochStart` and `epochEnd` (excluded) - /// @dev If the `uniV3Pool` parameter is equal to 0, then this function will return the campaigns for all pools + /// @notice Internal version of `getCampaignsBetween` function _getCampaignsBetween( uint32 start, uint32 end, @@ -615,8 +583,7 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { return (activeRewards, i); } - /// @notice Gets the list of all the distributions for `uniV3Pool` that have been active between `epochStart` and `epochEnd` (excluded) - /// @dev If the `uniV3Pool` parameter is equal to 0, then this function will return the distributions for all pools + /// @notice Internal version of `getDistributionsBetweenEpochs` function _getDistributionsBetweenEpochs( uint32 epochStart, uint32 epochEnd, diff --git a/contracts/deprecated/OldDistributionCreator.sol b/contracts/deprecated/OldDistributionCreator.sol index 0579af9..47745a7 100644 --- a/contracts/deprecated/OldDistributionCreator.sol +++ b/contracts/deprecated/OldDistributionCreator.sol @@ -35,10 +35,10 @@ pragma solidity ^0.8.17; -import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; -import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; +import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "../interfaces/external/uniswap/IUniswapV3Pool.sol"; import "../interfaces/external/algebra/IAlgebraPool.sol"; @@ -47,7 +47,13 @@ import "../struct/DistributionParameters.sol"; import "../struct/ExtensiveDistributionParameters.sol"; import "../struct/RewardTokenAmounts.sol"; -/// @title OldDistributionCreator +interface IDistributionCreator { + function tryGetExtensiveDistributionParameters( + DistributionParameters memory distribution + ) external view returns (bool success, ExtensiveDistributionParameters memory extensiveParams); +} + +/// @title DistributionCreator /// @author Angle Labs, Inc. /// @notice Manages the distribution of rewards across different pools with concentrated liquidity (like on Uniswap V3) /// @dev This contract is mostly a helper for APIs built on top of Merkl @@ -137,7 +143,12 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice Checks whether an address has signed the message or not modifier hasSigned() { - if (userSignatureWhitelist[msg.sender] == 0 && userSignatures[msg.sender] != messageHash) revert NotSigned(); + if ( + userSignatureWhitelist[msg.sender] == 0 && + userSignatures[msg.sender] != messageHash && + userSignatureWhitelist[tx.origin] == 0 && + userSignatures[tx.origin] != messageHash + ) revert NotSigned(); _; } @@ -279,9 +290,37 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { } /// @notice Returns the list of all currently active distributions on pools of supported AMMs (like Uniswap V3) - function getActiveDistributions() external view returns (ExtensiveDistributionParameters[] memory) { + function getActiveDistributions() + external + view + returns (ExtensiveDistributionParameters[] memory searchDistributions) + { + uint32 roundedEpoch = _getRoundedEpoch(uint32(block.timestamp)); + (searchDistributions, ) = _getPoolDistributionsBetweenEpochs( + address(0), + roundedEpoch, + roundedEpoch + EPOCH_DURATION, + 0, + type(uint32).max + ); + } + + /// @notice Similar to `getActiveDistributions()` with additional parameters to prevent out of gas error + /// @param skip Disregard distibutions with a global index lower than `skip` + /// @param first Limit the length of the returned array to `first` + /// @return searchDistributions Eligible distributions + /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions + /// For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution` + function getActiveDistributions( + uint32 skip, + uint32 first + ) + external + view + returns (ExtensiveDistributionParameters[] memory searchDistributions, uint256 lastIndexDistribution) + { uint32 roundedEpoch = _getRoundedEpoch(uint32(block.timestamp)); - return _getPoolDistributionsBetweenEpochs(address(0), roundedEpoch, roundedEpoch + EPOCH_DURATION); + return _getPoolDistributionsBetweenEpochs(address(0), roundedEpoch, roundedEpoch + EPOCH_DURATION, skip, first); } /// @notice Returns the list of all the reward tokens supported as well as their minimum amounts @@ -308,9 +347,32 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice Returns the list of all the distributions that were or that are going to be live at /// a specific epoch - function getDistributionsForEpoch(uint32 epoch) external view returns (ExtensiveDistributionParameters[] memory) { + function getDistributionsForEpoch( + uint32 epoch + ) external view returns (ExtensiveDistributionParameters[] memory searchDistributions) { uint32 roundedEpoch = _getRoundedEpoch(epoch); - return _getPoolDistributionsBetweenEpochs(address(0), roundedEpoch, roundedEpoch + EPOCH_DURATION); + (searchDistributions, ) = _getPoolDistributionsBetweenEpochs( + address(0), + roundedEpoch, + roundedEpoch + EPOCH_DURATION, + 0, + type(uint32).max + ); + } + + /// @notice Similar to `getDistributionsForEpoch(uint256 epoch)` with additional parameters to prevent out of gas error + /// @param skip Disregard distibutions with a global index lower than `skip` + /// @param first Limit the length of the returned array to `first` + /// @return searchDistributions Eligible distributions + /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions + /// For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution` + function getDistributionsForEpoch( + uint32 epoch, + uint32 skip, + uint32 first + ) external view returns (ExtensiveDistributionParameters[] memory, uint256 lastIndexDistribution) { + uint32 roundedEpoch = _getRoundedEpoch(epoch); + return _getPoolDistributionsBetweenEpochs(address(0), roundedEpoch, roundedEpoch + EPOCH_DURATION, skip, first); } /// @notice Gets the distributions that were or will be live at some point between `epochStart` (included) and `epochEnd` (excluded) @@ -319,23 +381,93 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { function getDistributionsBetweenEpochs( uint32 epochStart, uint32 epochEnd - ) external view returns (ExtensiveDistributionParameters[] memory) { - return _getPoolDistributionsBetweenEpochs(address(0), _getRoundedEpoch(epochStart), _getRoundedEpoch(epochEnd)); + ) external view returns (ExtensiveDistributionParameters[] memory searchDistributions) { + (searchDistributions, ) = _getPoolDistributionsBetweenEpochs( + address(0), + _getRoundedEpoch(epochStart), + _getRoundedEpoch(epochEnd), + 0, + type(uint32).max + ); + } + + /// @notice Similar to `getDistributionsBetweenEpochs(uint256 epochStart, uint256 epochEnd)` with additional parameters to prevent out of gas error + /// @param skip Disregard distibutions with a global index lower than `skip` + /// @param first Limit the length of the returned array to `first` + /// @return searchDistributions Eligible distributions + /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions + /// For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution` + function getDistributionsBetweenEpochs( + uint32 epochStart, + uint32 epochEnd, + uint32 skip, + uint32 first + ) external view returns (ExtensiveDistributionParameters[] memory, uint256 lastIndexDistribution) { + return + _getPoolDistributionsBetweenEpochs( + address(0), + _getRoundedEpoch(epochStart), + _getRoundedEpoch(epochEnd), + skip, + first + ); } /// @notice Returns the list of all distributions that were or will be live after `epochStart` (included) function getDistributionsAfterEpoch( uint32 epochStart - ) external view returns (ExtensiveDistributionParameters[] memory) { - return _getPoolDistributionsBetweenEpochs(address(0), _getRoundedEpoch(epochStart), type(uint32).max); + ) external view returns (ExtensiveDistributionParameters[] memory searchDistributions) { + (searchDistributions, ) = _getPoolDistributionsBetweenEpochs( + address(0), + _getRoundedEpoch(epochStart), + type(uint32).max, + 0, + type(uint32).max + ); + } + + /// @notice Similar to `getDistributionsAfterEpoch(uint256 epochStart)` with additional parameters to prevent out of gas error + /// @param skip Disregard distibutions with a global index lower than `skip` + /// @param first Limit the length of the returned array to `first` + /// @return searchDistributions Eligible distributions + /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions + /// For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution` + function getDistributionsAfterEpoch( + uint32 epochStart, + uint32 skip, + uint32 first + ) external view returns (ExtensiveDistributionParameters[] memory, uint256 lastIndexDistribution) { + return + _getPoolDistributionsBetweenEpochs(address(0), _getRoundedEpoch(epochStart), type(uint32).max, skip, first); } /// @notice Returns the list of all currently active distributions for a specific UniswapV3 pool function getActivePoolDistributions( address uniV3Pool - ) external view returns (ExtensiveDistributionParameters[] memory) { + ) external view returns (ExtensiveDistributionParameters[] memory searchDistributions) { + uint32 roundedEpoch = _getRoundedEpoch(uint32(block.timestamp)); + (searchDistributions, ) = _getPoolDistributionsBetweenEpochs( + uniV3Pool, + roundedEpoch, + roundedEpoch + EPOCH_DURATION, + 0, + type(uint32).max + ); + } + + /// @notice Similar to `getActivePoolDistributions(address uniV3Pool)` with additional parameters to prevent out of gas error + /// @param skip Disregard distibutions with a global index lower than `skip` + /// @param first Limit the length of the returned array to `first` + /// @return searchDistributions Eligible distributions + /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions + /// For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution` + function getActivePoolDistributions( + address uniV3Pool, + uint32 skip, + uint32 first + ) external view returns (ExtensiveDistributionParameters[] memory, uint256 lastIndexDistribution) { uint32 roundedEpoch = _getRoundedEpoch(uint32(block.timestamp)); - return _getPoolDistributionsBetweenEpochs(uniV3Pool, roundedEpoch, roundedEpoch + EPOCH_DURATION); + return _getPoolDistributionsBetweenEpochs(uniV3Pool, roundedEpoch, roundedEpoch + EPOCH_DURATION, skip, first); } /// @notice Returns the list of all the distributions that were or that are going to be live at a @@ -343,9 +475,31 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { function getPoolDistributionsForEpoch( address uniV3Pool, uint32 epoch - ) external view returns (ExtensiveDistributionParameters[] memory) { + ) external view returns (ExtensiveDistributionParameters[] memory searchDistributions) { uint32 roundedEpoch = _getRoundedEpoch(epoch); - return _getPoolDistributionsBetweenEpochs(uniV3Pool, roundedEpoch, roundedEpoch + EPOCH_DURATION); + (searchDistributions, ) = _getPoolDistributionsBetweenEpochs( + uniV3Pool, + roundedEpoch, + roundedEpoch + EPOCH_DURATION, + 0, + type(uint32).max + ); + } + + /// @notice Similar to `getPoolDistributionsForEpoch(address uniV3Pool,uint32 epoch)` with additional parameters to prevent out of gas error + /// @param skip Disregard distibutions with a global index lower than `skip` + /// @param first Limit the length of the returned array to `first` + /// @return searchDistributions Eligible distributions + /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions + /// For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution` + function getPoolDistributionsForEpoch( + address uniV3Pool, + uint32 epoch, + uint32 skip, + uint32 first + ) external view returns (ExtensiveDistributionParameters[] memory, uint256 lastIndexDistribution) { + uint32 roundedEpoch = _getRoundedEpoch(epoch); + return _getPoolDistributionsBetweenEpochs(uniV3Pool, roundedEpoch, roundedEpoch + EPOCH_DURATION, skip, first); } /// @notice Returns the list of all distributions that were or will be live at some point between @@ -354,8 +508,37 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { address uniV3Pool, uint32 epochStart, uint32 epochEnd - ) external view returns (ExtensiveDistributionParameters[] memory) { - return _getPoolDistributionsBetweenEpochs(uniV3Pool, _getRoundedEpoch(epochStart), _getRoundedEpoch(epochEnd)); + ) external view returns (ExtensiveDistributionParameters[] memory searchDistributions) { + (searchDistributions, ) = _getPoolDistributionsBetweenEpochs( + uniV3Pool, + _getRoundedEpoch(epochStart), + _getRoundedEpoch(epochEnd), + 0, + type(uint32).max + ); + } + + /// @notice Similar to `getPoolDistributionsBetweenEpochs(address uniV3Pool,uint32 epochStart, uint32 epochEnd)` with additional parameters to prevent out of gas error + /// @param skip Disregard distibutions with a global index lower than `skip` + /// @param first Limit the length of the returned array to `first` + /// @return searchDistributions Eligible distributions + /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions + /// For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution` + function getPoolDistributionsBetweenEpochs( + address uniV3Pool, + uint32 epochStart, + uint32 epochEnd, + uint32 skip, + uint32 first + ) external view returns (ExtensiveDistributionParameters[] memory, uint256 lastIndexDistribution) { + return + _getPoolDistributionsBetweenEpochs( + uniV3Pool, + _getRoundedEpoch(epochStart), + _getRoundedEpoch(epochEnd), + skip, + first + ); } /// @notice Returns the list of all distributions that were or will be live after `epochStart` (included) @@ -363,8 +546,30 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { function getPoolDistributionsAfterEpoch( address uniV3Pool, uint32 epochStart - ) external view returns (ExtensiveDistributionParameters[] memory) { - return _getPoolDistributionsBetweenEpochs(uniV3Pool, _getRoundedEpoch(epochStart), type(uint32).max); + ) external view returns (ExtensiveDistributionParameters[] memory searchDistributions) { + (searchDistributions, ) = _getPoolDistributionsBetweenEpochs( + uniV3Pool, + _getRoundedEpoch(epochStart), + type(uint32).max, + 0, + type(uint32).max + ); + } + + /// @notice Similar to `getPoolDistributionsAfterEpoch(address uniV3Pool,uint32 epochStart)` with additional parameters to prevent out of gas error + /// @param skip Disregard distibutions with a global index lower than `skip` + /// @param first Limit the length of the returned array to `first` + /// @return searchDistributions Eligible distributions + /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions + /// For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution` + function getPoolDistributionsAfterEpoch( + address uniV3Pool, + uint32 epochStart, + uint32 skip, + uint32 first + ) external view returns (ExtensiveDistributionParameters[] memory, uint256 lastIndexDistribution) { + return + _getPoolDistributionsBetweenEpochs(uniV3Pool, _getRoundedEpoch(epochStart), type(uint32).max, skip, first); } // ============================ GOVERNANCE FUNCTIONS =========================== @@ -475,26 +680,14 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { } /// @notice Fetches extra data about the parameters in a distribution - function _getExtensiveDistributionParameters( + function getExtensiveDistributionParameters( DistributionParameters memory distribution - ) internal view returns (ExtensiveDistributionParameters memory extensiveParams) { + ) external view returns (ExtensiveDistributionParameters memory extensiveParams) { extensiveParams.base = distribution; try IUniswapV3Pool(distribution.uniV3Pool).fee() returns (uint24 fee) { extensiveParams.poolFee = fee; } catch { - try IAlgebraPool(distribution.uniV3Pool).globalState() returns ( - uint160, - int24, - uint16 fee, - uint16, - uint8, - uint8, - bool - ) { - extensiveParams.poolFee = uint24(fee); - } catch { - extensiveParams.poolFee = 0; - } + extensiveParams.poolFee = 0; } extensiveParams.token0 = _getUniswapTokenData( IERC20Metadata(IUniswapV3Pool(distribution.uniV3Pool).token0()), @@ -508,34 +701,56 @@ contract OldDistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { extensiveParams.rewardTokenDecimals = IERC20Metadata(distribution.rewardToken).decimals(); } + /// @notice Tries to fetch extra data about the parameters in a distribution + function tryGetExtensiveDistributionParameters( + DistributionParameters memory distribution + ) external returns (bool success, ExtensiveDistributionParameters memory extensiveParams) { + (bool callSuccess, bytes memory returndata) = address(this).delegatecall( + abi.encodeWithSelector(OldDistributionCreator.getExtensiveDistributionParameters.selector, distribution) + ); + success = callSuccess; + if (success) { + extensiveParams = abi.decode(returndata, (ExtensiveDistributionParameters)); + } + return (success, extensiveParams); + } + /// @notice Gets the list of all the distributions for `uniV3Pool` that have been active between `epochStart` and `epochEnd` (excluded) /// @dev If the `uniV3Pool` parameter is equal to 0, then this function will return the distributions for all pools function _getPoolDistributionsBetweenEpochs( address uniV3Pool, uint32 epochStart, - uint32 epochEnd - ) internal view returns (ExtensiveDistributionParameters[] memory) { + uint32 epochEnd, + uint32 skip, + uint32 first + ) internal view returns (ExtensiveDistributionParameters[] memory, uint256) { uint256 length; uint256 distributionListLength = distributionList.length; - ExtensiveDistributionParameters[] memory activeRewards = new ExtensiveDistributionParameters[]( - distributionListLength - ); - for (uint32 i; i < distributionListLength; ) { + uint256 returnSize = first > distributionListLength ? distributionListLength : first; + ExtensiveDistributionParameters[] memory activeRewards = new ExtensiveDistributionParameters[](returnSize); + uint32 i = skip; + while (i < distributionListLength) { DistributionParameters memory distribution = distributionList[i]; if ( _isDistributionLiveBetweenEpochs(distribution, epochStart, epochEnd) && (uniV3Pool == address(0) || distribution.uniV3Pool == uniV3Pool) ) { - activeRewards[length] = _getExtensiveDistributionParameters(distribution); - length += 1; + (bool success, ExtensiveDistributionParameters memory extensiveParams) = IDistributionCreator( + address(this) + ).tryGetExtensiveDistributionParameters(distribution); + if (success) { + activeRewards[length] = extensiveParams; + length += 1; + } } unchecked { ++i; } + if (length == returnSize) break; } assembly { mstore(activeRewards, length) } - return activeRewards; + return (activeRewards, i); } } diff --git a/contracts/deprecated/OldDistributor.sol b/contracts/deprecated/OldDistributor.sol index c655796..1bd2a9b 100644 --- a/contracts/deprecated/OldDistributor.sol +++ b/contracts/deprecated/OldDistributor.sol @@ -35,9 +35,9 @@ pragma solidity ^0.8.17; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/utils/math/SafeCast.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "../utils/UUPSHelper.sol"; @@ -54,14 +54,18 @@ struct MerkleTree { struct Claim { uint208 amount; uint48 timestamp; + bytes32 merkleRoot; } -/// @title OldDistributor +/// @title Distributor /// @notice Allows LPs on AMMs with concentrated liquidity to claim the rewards that were distributed to them /// @author Angle Labs. Inc -contract OldDistributor is UUPSHelper { +contract Distributor is UUPSHelper { using SafeERC20 for IERC20; + /// @notice Epoch duration + uint32 internal constant _EPOCH_DURATION = 3600; + // ================================= VARIABLES ================================= /// @notice Tree of claimable tokens through this contract @@ -80,10 +84,10 @@ contract OldDistributor is UUPSHelper { /// @dev Used to store if there is an ongoing dispute address public disputer; - /// @notice Last time the `tree` was updated - uint48 public lastTreeUpdate; + /// @notice When the current tree will become valid + uint48 public endOfDisputePeriod; - /// @notice Time before which a change in a tree becomes effective + /// @notice Time after which a change in a tree becomes effective, in EPOCH_DURATION uint48 public disputePeriod; /// @notice Amount to deposit to freeze the roots update @@ -105,16 +109,17 @@ contract OldDistributor is UUPSHelper { // =================================== EVENTS ================================== - event Claimed(address user, address token, uint256 amount); + event Claimed(address indexed user, address indexed token, uint256 amount); + event DisputeAmountUpdated(uint256 _disputeAmount); event Disputed(string reason); event DisputePeriodUpdated(uint48 _disputePeriod); - event DisputeTokenUpdated(address indexed _disputeToken); - event DisputeAmountUpdated(uint256 _disputeAmount); event DisputeResolved(bool valid); - event OperatorClaimingToggled(address user, bool isEnabled); - event OperatorToggled(address user, address operator, bool isWhitelisted); + event DisputeTokenUpdated(address indexed _disputeToken); + event OperatorClaimingToggled(address indexed user, bool isEnabled); + event OperatorToggled(address indexed user, address indexed operator, bool isWhitelisted); event Recovered(address indexed token, address indexed to, uint256 amount); - event TreeUpdated(bytes32 merkleRoot, bytes32 ipfsHash); + event Revoked(); // With this event an indexer could maintain a table (timestamp, merkleRootUpdate) + event TreeUpdated(bytes32 merkleRoot, bytes32 ipfsHash, uint48 endOfDisputePeriod); event TrustedToggled(address indexed eoa, bool trust); // ================================= MODIFIERS ================================= @@ -181,7 +186,7 @@ contract OldDistributor is UUPSHelper { // Closing reentrancy gate here uint256 toSend = amount - claimed[user][token].amount; - claimed[user][token] = Claim(SafeCast.toUint208(amount), uint48(block.timestamp)); + claimed[user][token] = Claim(SafeCast.toUint208(amount), uint48(block.timestamp), getMerkleRoot()); IERC20(token).safeTransfer(user, toSend); emit Claimed(user, token, toSend); @@ -193,7 +198,7 @@ contract OldDistributor is UUPSHelper { /// @notice Returns the MerkleRoot that is currently live for the contract function getMerkleRoot() public view returns (bytes32) { - if (block.timestamp - lastTreeUpdate >= disputePeriod) return tree.merkleRoot; + if (block.timestamp >= endOfDisputePeriod && disputer == address(0)) return tree.merkleRoot; else return lastTree.merkleRoot; } @@ -212,21 +217,24 @@ contract OldDistributor is UUPSHelper { disputer != address(0) || // A trusted address cannot update a tree right after a precedent tree update otherwise it can de facto // validate a tree which has not passed the dispute period - ((canUpdateMerkleRoot[msg.sender] != 1 || block.timestamp - lastTreeUpdate < disputePeriod) && + ((canUpdateMerkleRoot[msg.sender] != 1 || block.timestamp < endOfDisputePeriod) && !core.isGovernorOrGuardian(msg.sender)) ) revert NotTrusted(); MerkleTree memory _lastTree = tree; tree = _tree; lastTree = _lastTree; - lastTreeUpdate = uint48(block.timestamp); - emit TreeUpdated(_tree.merkleRoot, _tree.ipfsHash); + + uint48 _endOfPeriod = _endOfDisputePeriod(uint48(block.timestamp)); + endOfDisputePeriod = _endOfPeriod; + emit TreeUpdated(_tree.merkleRoot, _tree.ipfsHash, _endOfPeriod); } /// @notice Freezes the Merkle tree update until the dispute is resolved /// @dev Requires a deposit of `disputeToken` that'll be slashed if the dispute is not accepted - /// @dev It is only possible to create a dispute for `disputePeriod` after each tree update + /// @dev It is only possible to create a dispute within `disputePeriod` after each tree update function disputeTree(string memory reason) external { - if (block.timestamp - lastTreeUpdate >= disputePeriod) revert InvalidDispute(); + if (disputer != address(0)) revert UnresolvedDispute(); + if (block.timestamp >= endOfDisputePeriod) revert InvalidDispute(); IERC20(disputeToken).safeTransferFrom(msg.sender, address(this), disputeAmount); disputer = msg.sender; emit Disputed(reason); @@ -242,7 +250,7 @@ contract OldDistributor is UUPSHelper { _revokeTree(); } else { IERC20(disputeToken).safeTransfer(msg.sender, disputeAmount); - lastTreeUpdate = uint48(block.timestamp); + endOfDisputePeriod = _endOfDisputePeriod(uint48(block.timestamp)); } disputer = address(0); emit DisputeResolved(valid); @@ -275,9 +283,8 @@ contract OldDistributor is UUPSHelper { emit Recovered(tokenAddress, to, amountToRecover); } - /// @notice Sets the dispute period before which a tree update becomes effective + /// @notice Sets the dispute period after which a tree update becomes effective function setDisputePeriod(uint48 _disputePeriod) external onlyGovernorOrGuardian { - if (_disputePeriod > block.timestamp) revert InvalidParam(); disputePeriod = uint48(_disputePeriod); emit DisputePeriodUpdated(_disputePeriod); } @@ -301,9 +308,20 @@ contract OldDistributor is UUPSHelper { /// @notice Fallback to the last version of the tree function _revokeTree() internal { MerkleTree memory _tree = lastTree; - lastTreeUpdate = 0; + endOfDisputePeriod = 0; tree = _tree; - emit TreeUpdated(_tree.merkleRoot, _tree.ipfsHash); + emit Revoked(); + emit TreeUpdated( + _tree.merkleRoot, + _tree.ipfsHash, + (uint48(block.timestamp) / _EPOCH_DURATION) * (_EPOCH_DURATION) // Last hour + ); + } + + /// @notice Returns the end of the dispute period + /// @dev treeUpdate is rounded up to next hour and then `disputePeriod` hours are added + function _endOfDisputePeriod(uint48 treeUpdate) internal view returns (uint48) { + return ((treeUpdate - 1) / _EPOCH_DURATION + 1 + disputePeriod) * (_EPOCH_DURATION); } /// @notice Checks the validity of a proof diff --git a/package.json b/package.json index 3e34831..7275845 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "url": "https://github.com/AngleProtocol/merkl-contracts/issues" }, "devDependencies": { - "@angleprotocol/sdk": "3.0.87", + "@angleprotocol/sdk": "0.21.1", "@ethersproject/abi": "^5.7.0", "@ethersproject/providers": "^5.7.1", "@nomicfoundation/hardhat-chai-matchers": "^1.0.3", diff --git a/scripts/checkUpgradeability.ts b/scripts/checkUpgradeability.ts index 537379f..a1dea6f 100644 --- a/scripts/checkUpgradeability.ts +++ b/scripts/checkUpgradeability.ts @@ -44,6 +44,14 @@ async function main() { testUpgradeability('Distributor', 'contracts/Distributor.sol'); testStorage('OldDistributor', 'contracts/deprecated/OldDistributor.sol', 'Distributor', 'contracts/Distributor.sol'); + + testUpgradeability('DistributionCreator', 'contracts/DistributionCreator.sol'); + testStorage( + 'OldDistributionCreator', + 'contracts/deprecated/OldDistributionCreator.sol', + 'DistributionCreator', + 'contracts/DistributionCreator.sol', + ); } main().catch(error => { diff --git a/scripts/mainnet-fork/migrationAngleDistributor.ts b/scripts/mainnet-fork/upgradeDistributionCreator.ts similarity index 93% rename from scripts/mainnet-fork/migrationAngleDistributor.ts rename to scripts/mainnet-fork/upgradeDistributionCreator.ts index f19358e..f046b5d 100644 --- a/scripts/mainnet-fork/migrationAngleDistributor.ts +++ b/scripts/mainnet-fork/upgradeDistributionCreator.ts @@ -4,12 +4,10 @@ import yargs from 'yargs'; import { deployUpgradeableUUPS, increaseTime, ZERO_ADDRESS } from '../../test/hardhat/utils/helpers'; import { - AngleDistributor, - AngleDistributor__factory, DistributionCreator, + DistributionCreator__factory, ERC20, ERC20__factory, - MerkleRewardManager__factory, MockMerklGaugeMiddleman, MockMerklGaugeMiddleman__factory, ProxyAdmin, @@ -21,13 +19,22 @@ const argv = yargs.env('').boolean('ci').parseSync(); async function main() { let manager: DistributionCreator; - let angleDistributor: AngleDistributor; let middleman: MockMerklGaugeMiddleman; let angle: ERC20; let params: any; const { deploy } = deployments; const [deployer] = await ethers.getSigners(); + + const manager = new ethers.Contract( + proxyAdminAddress, + ProxyAdmin__factory.createInterface(), + governorSigner, + ) as ProxyAdmin; + + const newImplementation = await new DistributionCreator__factory(deployer).deploy(); + await manager.connect(governor).upgradeTo(newImplementation.address); + const proxyAdminAddress = CONTRACTS_ADDRESSES[ChainId.MAINNET].ProxyAdmin!; const governor = CONTRACTS_ADDRESSES[ChainId.MAINNET].Governor! as string; const coreBorrow = CONTRACTS_ADDRESSES[ChainId.MAINNET].CoreBorrow! as string; From ebca692528c9b5a78e098b90c36969ce31bcd0fb Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Wed, 31 Jan 2024 15:45:11 +0100 Subject: [PATCH 3/5] feat merkl V2 iterations --- contracts/DistributionCreator.sol | 63 +- contracts/struct/CampaignParameters.sol | 19 +- package.json | 2 +- .../upgradeDistributionCreator.ts | 121 +--- yarn.lock | 537 +++++++++++++----- 5 files changed, 458 insertions(+), 284 deletions(-) diff --git a/contracts/DistributionCreator.sol b/contracts/DistributionCreator.sol index 88266b0..65541f5 100644 --- a/contracts/DistributionCreator.sol +++ b/contracts/DistributionCreator.sol @@ -190,13 +190,13 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Creates a `campaign` to incentivize a given pool for a specific period of time - /// @return campaignAmount How many reward tokens are actually taken into consideration in the contract + /// @return The campaignId of the new campaign /// @dev If the campaign is badly specified, it will not be handled by the campaign script and rewards may be lost /// @dev Reward tokens sent as part of campaigns must have been whitelisted before and amounts /// sent should be bigger than a minimum amount specific to each token /// @dev This function reverts if the sender has not accepted the terms and conditions - function createCampaign(CampaignParameters memory campaign) external nonReentrant hasSigned returns (bytes32) { - return _createCampaign(campaign); + function createCampaign(CampaignParameters memory newCampaign) external nonReentrant hasSigned returns (bytes32) { + return _createCampaign(newCampaign); } /// @notice Same as the function above but for multiple campaigns at once @@ -231,11 +231,11 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// @notice Combines signing the message and creating a campaign function signAndCreateCampaign( - CampaignParameters memory campaign, + CampaignParameters memory newCampaign, bytes calldata signature ) external returns (bytes32) { _sign(signature); - return _createCampaign(campaign); + return _createCampaign(newCampaign); } /// @notice Creates a `distribution` to incentivize a given pool for a specific period of time @@ -286,17 +286,17 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { /// - `campaign.campaignData` /// This prevents the creation by the same account of two campaigns with the same parameters /// which is not a huge issue - function campaignId(CampaignParameters memory campaign) public pure returns (bytes32) { + function campaignId(CampaignParameters memory campaignData) public pure returns (bytes32) { return bytes32( keccak256( abi.encodePacked( - campaign.creator, - campaign.rewardToken, - campaign.campaignType, - campaign.startTimestamp, - campaign.duration, - campaign.campaignData + campaignData.creator, + campaignData.rewardToken, + campaignData.campaignType, + campaignData.startTimestamp, + campaignData.duration, + campaignData.campaignData ) ) ); @@ -440,33 +440,33 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Internal version of `createCampaign` - function _createCampaign(CampaignParameters memory campaign) internal returns (bytes32) { - uint256 rewardTokenMinAmount = rewardTokenMinAmounts[campaign.rewardToken]; + function _createCampaign(CampaignParameters memory newCampaign) internal returns (bytes32) { + uint256 rewardTokenMinAmount = rewardTokenMinAmounts[newCampaign.rewardToken]; // if epoch parameters lead to a past campaign - if (campaign.startTimestamp < block.timestamp) revert CampaignSouldStartInFuture(); + if (newCampaign.startTimestamp < block.timestamp) revert CampaignSouldStartInFuture(); // if the campaign doesn't last at least one second - if (campaign.duration == 0) revert CampaignDurationIsZero(); + if (newCampaign.duration == 0) revert CampaignDurationIsZero(); // if the reward token is not whitelisted as an incentive token if (rewardTokenMinAmount == 0) revert CampaignRewardTokenNotWhitelisted(); // if the amount distributed is too small with respect to what is allowed - if ((campaign.amount * HOUR) / campaign.duration < rewardTokenMinAmount) revert CampaignRewardTooLow(); + if ((newCampaign.amount * HOUR) / newCampaign.duration < rewardTokenMinAmount) revert CampaignRewardTooLow(); - if (campaign.creator == address(0)) campaign.creator = msg.sender; + if (newCampaign.creator == address(0)) newCampaign.creator = msg.sender; // Computing fees: these are waived for whitelisted addresses and if there is a whitelisted token in a pool - uint256 _fees = campaignSpecificFees[campaign.campaignType]; + uint256 _fees = campaignSpecificFees[newCampaign.campaignType]; if (_fees == 0) _fees = defaultFees; - uint256 campaignAmountMinusFees = _computeFees(_fees, campaign.amount, campaign.rewardToken); - campaign.amount = campaignAmountMinusFees; + uint256 campaignAmountMinusFees = _computeFees(_fees, newCampaign.amount, newCampaign.rewardToken); + newCampaign.amount = campaignAmountMinusFees; - campaign.campaignId = campaignId(campaign); + newCampaign.campaignId = campaignId(newCampaign); - if (_campaignLookup[campaign.campaignId] != 0) revert CampaignAlreadyExists(); - _campaignLookup[campaign.campaignId] = campaignList.length + 1; - campaignList.push(campaign); - emit NewCampaign(campaign); + if (_campaignLookup[newCampaign.campaignId] != 0) revert CampaignAlreadyExists(); + _campaignLookup[newCampaign.campaignId] = campaignList.length + 1; + campaignList.push(newCampaign); + emit NewCampaign(newCampaign); - return campaign.campaignId; + return newCampaign.campaignId; } /// @notice Converts the deprecated distribution type into a campaign @@ -567,9 +567,12 @@ contract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable { CampaignParameters[] memory activeRewards = new CampaignParameters[](returnSize); uint32 i = skip; while (i < campaignListLength) { - CampaignParameters memory campaign = campaignList[i]; - if (campaign.startTimestamp + campaign.duration > start && campaign.startTimestamp < end) { - activeRewards[length] = campaign; + CampaignParameters memory campaignToProcess = campaignList[i]; + if ( + campaignToProcess.startTimestamp + campaignToProcess.duration > start && + campaignToProcess.startTimestamp < end + ) { + activeRewards[length] = campaignToProcess; length += 1; } unchecked { diff --git a/contracts/struct/CampaignParameters.sol b/contracts/struct/CampaignParameters.sol index 7423f7d..4f75f4e 100644 --- a/contracts/struct/CampaignParameters.sol +++ b/contracts/struct/CampaignParameters.sol @@ -3,14 +3,27 @@ pragma solidity ^0.8.17; struct CampaignParameters { - // Populated once created + // POPULATED ONCE CREATED + + // ID of the campaign. This can be left as a null bytes32 when creating campaigns + // on Merkl. bytes32 campaignId; - // Chosen by campaign creator + // CHOSEN BY CAMPAIGN CREATOR + + // Address of the campaign creator, if marked as address(0), it will be overriden with the + // address of the `msg.sender` creating the campaign address creator; + // Address of the token used as a reward address rewardToken; + // Amount of `rewardToken` to distribute across all the epochs + // Amount distributed per epoch is `amount/numEpoch` uint256 amount; + // Type of campaign uint32 campaignType; + // Timestamp at which the campaign should start uint32 startTimestamp; - uint32 duration; // in seconds, has to be a multiple of EPOCH + // Duration of the campaign in seconds. Has to be a multiple of EPOCH = 3600 + uint32 duration; + // Extra data to pass to specify the campaign bytes campaignData; } diff --git a/package.json b/package.json index 7275845..5fdd5bc 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "eslint-plugin-promise": "^6.0.0", "eslint-plugin-standard": "5.0.0", "ethers": "^5.7.1", - "hardhat": "^2.12.6", + "hardhat": "^2.19.4", "hardhat-abi-exporter": "2.2.1", "hardhat-contract-sizer": "2.0.3", "hardhat-deploy": "^0.11.23", diff --git a/scripts/mainnet-fork/upgradeDistributionCreator.ts b/scripts/mainnet-fork/upgradeDistributionCreator.ts index f046b5d..61864dc 100644 --- a/scripts/mainnet-fork/upgradeDistributionCreator.ts +++ b/scripts/mainnet-fork/upgradeDistributionCreator.ts @@ -1,4 +1,4 @@ -import { ChainId, CONTRACTS_ADDRESSES } from '@angleprotocol/sdk'; +import { ChainId, registry } from '@angleprotocol/sdk'; import { deployments, ethers, network, web3 } from 'hardhat'; import yargs from 'yargs'; @@ -26,42 +26,7 @@ async function main() { const { deploy } = deployments; const [deployer] = await ethers.getSigners(); - const manager = new ethers.Contract( - proxyAdminAddress, - ProxyAdmin__factory.createInterface(), - governorSigner, - ) as ProxyAdmin; - - const newImplementation = await new DistributionCreator__factory(deployer).deploy(); - await manager.connect(governor).upgradeTo(newImplementation.address); - - const proxyAdminAddress = CONTRACTS_ADDRESSES[ChainId.MAINNET].ProxyAdmin!; - const governor = CONTRACTS_ADDRESSES[ChainId.MAINNET].Governor! as string; - const coreBorrow = CONTRACTS_ADDRESSES[ChainId.MAINNET].CoreBorrow! as string; - const distributor = CONTRACTS_ADDRESSES[ChainId.MAINNET].Distributor! as string; - const angleDistributorAddress = CONTRACTS_ADDRESSES[ChainId.MAINNET].AngleDistributor! as string; - const angleAddress = CONTRACTS_ADDRESSES[ChainId.MAINNET].ANGLE! as string; - const agEURAddress = '0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8'; - // agEUR-USDC gauge address - const gaugeAddr = '0xEB7547a8a734b6fdDBB8Ce0C314a9E6485100a3C'; - - params = { - uniV3Pool: '0x735a26a57a0a0069dfabd41595a970faf5e1ee8b', - token: angleAddress, - positionWrappers: [], - wrapperTypes: [], - amount: parseAmount.gwei('100000'), - propToken0: 4000, - propToken1: 2000, - propFees: 4000, - isOutOfRangeIncentivized: 0, - epochStart: 0, - numEpoch: 168, - boostedReward: 0, - boostingAddress: ZERO_ADDRESS, - rewardId: web3.utils.soliditySha3('TEST') as string, - additionalData: web3.utils.soliditySha3('test2ng') as string, - }; + const governor = registry(ChainId.MAINNET)?.AngleLabs!; await network.provider.request({ method: 'hardhat_impersonateAccount', @@ -70,70 +35,30 @@ async function main() { await network.provider.send('hardhat_setBalance', [governor, '0x10000000000000000000000000000']); const governorSigner = await ethers.provider.getSigner(governor); - console.log('First deploying implementation for distributor'); - await deploy('AngleDistributor_NewImplementation', { - contract: 'AngleDistributor', - from: deployer.address, - log: !argv.ci, - }); - console.log('Success'); - - const distributorImplementationAddress = (await deployments.get('AngleDistributor_NewImplementation')).address; - - const contractProxyAdmin = new ethers.Contract( - proxyAdminAddress, - ProxyAdmin__factory.createInterface(), - governorSigner, - ) as ProxyAdmin; + const distributorAddress = registry(ChainId.MAINNET)?.Merkl?.DistributionCreator!; - angleDistributor = new ethers.Contract( - angleDistributorAddress, - AngleDistributor__factory.createInterface(), + manager = new ethers.Contract( + distributorAddress, + DistributionCreator__factory.createInterface(), governorSigner, - ) as AngleDistributor; + ) as DistributionCreator; - angle = new ethers.Contract(angleAddress, ERC20__factory.createInterface(), governorSigner) as ERC20; - - console.log('Now performing the upgrades'); - await ( - await contractProxyAdmin.connect(governorSigner).upgrade(angleDistributorAddress, distributorImplementationAddress) - ).wait(); - console.log('Success'); - - manager = (await deployUpgradeableUUPS(new MerkleRewardManager__factory(deployer))) as DistributionCreator; - await manager.initialize(coreBorrow, distributor, parseAmount.gwei('0.1')); - - middleman = (await new MockMerklGaugeMiddleman__factory(deployer).deploy(coreBorrow)) as MockMerklGaugeMiddleman; - - await middleman.setAddresses(angleDistributorAddress, angleAddress, manager.address); - - console.log('Toggling signature whitelist'); - await (await manager.connect(governorSigner).toggleSigningWhitelist(middleman.address)).wait(); - console.log('Toggling token whitelist'); - await manager.connect(governorSigner).toggleTokenWhitelist(agEURAddress); - - console.log('Setting the gauge on the middleman'); - await middleman.connect(governorSigner).setGauge(gaugeAddr, params); - console.log('Setting the middleman as a delegate for the gauge'); - await angleDistributor.connect(governorSigner).setDelegateGauge(gaugeAddr, middleman.address, true); - console.log('Setting allowance'); - await middleman.connect(governorSigner).setAngleAllowance(); - console.log(middleman.address); - - await increaseTime(86400 * 7); - - const angleBalanceDistr = await angle.balanceOf(distributor); - console.log(formatAmount.ether(angleBalanceDistr.toString())); - await angleDistributor.connect(governorSigner).distributeReward(gaugeAddr); - const angleBalanceDistr1 = await angle.balanceOf(distributor); - console.log(formatAmount.ether(angleBalanceDistr1.toString())); - await angleDistributor.connect(governorSigner).distributeReward(gaugeAddr); - const angleBalanceDistr2 = await angle.balanceOf(distributor); - console.log(formatAmount.ether(angleBalanceDistr2.toString())); - await increaseTime(86400 * 7); - await angleDistributor.connect(governorSigner).distributeReward(gaugeAddr); - const angleBalanceDistr3 = await angle.balanceOf(distributor); - console.log(formatAmount.ether(angleBalanceDistr3.toString())); + const newImplementation = await new DistributionCreator__factory(deployer).deploy(); + await manager.connect(governorSigner).upgradeTo(newImplementation.address); + + console.log(await manager.core()); + console.log(await manager.distributor()); + console.log(await manager.feeRecipient()); + console.log(await manager.defaultFees()); + console.log(await manager.message()); + console.log(await manager.distributionList(10)); + console.log(await manager.feeRebate(governor)); + console.log(await manager.isWhitelistedToken(registry(ChainId.MAINNET)?.agEUR?.AgToken!)); + console.log(await manager._nonces('0xfda462548ce04282f4b6d6619823a7c64fdc0185')); + console.log(await manager.userSignatureWhitelist('0xfda462548ce04282f4b6d6619823a7c64fdc0185')); + console.log(await manager.rewardTokens(0)); + console.log(await manager.campaignList(0)); + console.log(await manager.campaignSpecificFees(0)); } main().catch(error => { diff --git a/yarn.lock b/yarn.lock index ae821b1..e09fbbb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,11 +7,12 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@angleprotocol/sdk@3.0.87": - version "3.0.87" - resolved "https://registry.yarnpkg.com/@angleprotocol/sdk/-/sdk-3.0.87.tgz#20fdbb6b146dce0cb2a8fa37ade4c02a22fc3d0a" - integrity sha512-CFNbZJY96YL00OO0VjJONLU1bWF5tzn3BXxAhImBWMPsYGar9D/Jl/EABYhpok/WZI4gTqXNGJO7hQlF9d85Bg== +"@angleprotocol/sdk@0.21.1": + version "0.21.1" + resolved "https://npm.pkg.github.com/download/@angleprotocol/sdk/0.21.1/2f785e40f44da487d3af00dd4234e1aa5222fc46#2f785e40f44da487d3af00dd4234e1aa5222fc46" + integrity sha512-/4G2AL+ccDgL4DOUzSGp7c3yKLoWBy7+hav4/Tpkdo283MB9RSW4k84jJQov+OH3p5to3j5SBRfwrhND5zwu6Q== dependencies: + "@apollo/client" "^3.7.17" "@typechain/ethers-v5" "^10.0.0" "@types/lodash" "^4.14.180" ethers "^5.6.4" @@ -20,10 +21,30 @@ jsbi "^4.3.0" keccak256 "^1.0.6" lodash "^4.17.21" - merkletreejs "^0.3.9" + merkletreejs "^0.3.10" tiny-invariant "^1.1.0" typechain "^8.0.0" +"@apollo/client@^3.7.17": + version "3.9.0" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.9.0.tgz#269d8c67dc630df409a4b3ac749a72c6b887ba49" + integrity sha512-M6I7h9UF0MmW/eK1oTzuHewZRZmvNzvw4c7nXhvQnxIk0V0VeJWSmscRGQNtsNmk8WnBmgyV/1KOVNow2aOM8w== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + "@wry/caches" "^1.0.0" + "@wry/equality" "^0.5.6" + "@wry/trie" "^0.5.0" + graphql-tag "^2.12.6" + hoist-non-react-statics "^3.3.2" + optimism "^0.18.0" + prop-types "^15.7.2" + rehackt "0.0.3" + response-iterator "^0.2.6" + symbol-observable "^4.0.0" + ts-invariant "^0.10.3" + tslib "^2.3.0" + zen-observable-ts "^1.2.5" + "@babel/code-frame@^7.0.0": version "7.16.7" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" @@ -52,6 +73,42 @@ dependencies: regenerator-runtime "^0.13.4" +"@chainsafe/as-sha256@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz#3639df0e1435cab03f4d9870cc3ac079e57a6fc9" + integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== + +"@chainsafe/persistent-merkle-tree@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz#4c9ee80cc57cd3be7208d98c40014ad38f36f7ff" + integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/persistent-merkle-tree@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz#2b4a62c9489a5739dedd197250d8d2f5427e9f63" + integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + +"@chainsafe/ssz@^0.10.0": + version "0.10.2" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.10.2.tgz#c782929e1bb25fec66ba72e75934b31fd087579e" + integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.5.0" + +"@chainsafe/ssz@^0.9.2": + version "0.9.4" + resolved "https://registry.yarnpkg.com/@chainsafe/ssz/-/ssz-0.9.4.tgz#696a8db46d6975b600f8309ad3a12f7c0e310497" + integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== + dependencies: + "@chainsafe/as-sha256" "^0.3.1" + "@chainsafe/persistent-merkle-tree" "^0.4.2" + case "^1.6.3" + "@ensdomains/address-encoder@^0.1.7": version "0.1.9" resolved "https://registry.npmjs.org/@ensdomains/address-encoder/-/address-encoder-0.1.9.tgz" @@ -806,6 +863,32 @@ bech32 "1.1.4" ws "7.4.6" +"@ethersproject/providers@^5.7.2": + version "5.7.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" + integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== + dependencies: + "@ethersproject/abstract-provider" "^5.7.0" + "@ethersproject/abstract-signer" "^5.7.0" + "@ethersproject/address" "^5.7.0" + "@ethersproject/base64" "^5.7.0" + "@ethersproject/basex" "^5.7.0" + "@ethersproject/bignumber" "^5.7.0" + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/constants" "^5.7.0" + "@ethersproject/hash" "^5.7.0" + "@ethersproject/logger" "^5.7.0" + "@ethersproject/networks" "^5.7.0" + "@ethersproject/properties" "^5.7.0" + "@ethersproject/random" "^5.7.0" + "@ethersproject/rlp" "^5.7.0" + "@ethersproject/sha2" "^5.7.0" + "@ethersproject/strings" "^5.7.0" + "@ethersproject/transactions" "^5.7.0" + "@ethersproject/web" "^5.7.0" + bech32 "1.1.4" + ws "7.4.6" + "@ethersproject/random@5.5.1", "@ethersproject/random@^5.5.0": version "5.5.1" resolved "https://registry.npmjs.org/@ethersproject/random/-/random-5.5.1.tgz" @@ -1181,6 +1264,11 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" +"@graphql-typed-document-node/core@^3.1.1": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@humanwhocodes/config-array@^0.11.13": version "0.11.13" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" @@ -1242,29 +1330,31 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/ethereumjs-block@^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz" - integrity sha512-bk8uP8VuexLgyIZAHExH1QEovqx0Lzhc9Ntm63nCRKLHXIZkobaFaeCVwTESV7YkPKUk7NiK11s8ryed4CS9yA== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" +"@nomicfoundation/ethereumjs-block@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz#13a7968f5964f1697da941281b7f7943b0465d04" + integrity sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q== + dependencies: + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" ethereum-cryptography "0.1.3" + ethers "^5.7.1" -"@nomicfoundation/ethereumjs-blockchain@^6.0.0": - version "6.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz" - integrity sha512-pLFEoea6MWd81QQYSReLlLfH7N9v7lH66JC/NMPN848ySPPQA5renWnE7wPByfQFzNrPBuDDRFFULMDmj1C0xw== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-ethash" "^2.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" +"@nomicfoundation/ethereumjs-blockchain@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz#45323b673b3d2fab6b5008535340d1b8fea7d446" + integrity sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-ethash" "3.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" abstract-level "^1.0.3" debug "^4.3.3" ethereum-cryptography "0.1.3" @@ -1272,105 +1362,105 @@ lru-cache "^5.1.1" memory-level "^1.0.0" -"@nomicfoundation/ethereumjs-common@^3.0.0": - version "3.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz" - integrity sha512-WS7qSshQfxoZOpHG/XqlHEGRG1zmyjYrvmATvc4c62+gZXgre1ymYP8ZNgx/3FyZY0TWe9OjFlKOfLqmgOeYwA== +"@nomicfoundation/ethereumjs-common@4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz#a15d1651ca36757588fdaf2a7d381a150662a3c3" + integrity sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg== dependencies: - "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@nomicfoundation/ethereumjs-util" "9.0.2" crc-32 "^1.2.0" -"@nomicfoundation/ethereumjs-ethash@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz" - integrity sha512-WpDvnRncfDUuXdsAXlI4lXbqUDOA+adYRQaEezIkxqDkc+LDyYDbd/xairmY98GnQzo1zIqsIL6GB5MoMSJDew== +"@nomicfoundation/ethereumjs-ethash@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz#da77147f806401ee996bfddfa6487500118addca" + integrity sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg== dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" abstract-level "^1.0.3" bigint-crypto-utils "^3.0.23" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-evm@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz" - integrity sha512-hVS6qRo3V1PLKCO210UfcEQHvlG7GqR8iFzp0yyjTg2TmJQizcChKgWo8KFsdMw6AyoLgLhHGHw4HdlP8a4i+Q== +"@nomicfoundation/ethereumjs-evm@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz#4c2f4b84c056047102a4fa41c127454e3f0cfcf6" + integrity sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ== dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@types/async-eventemitter" "^0.2.1" - async-eventemitter "^0.2.4" + "@ethersproject/providers" "^5.7.1" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" mcl-wasm "^0.7.1" rustbn.js "~0.2.0" -"@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": - version "4.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz" - integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== +"@nomicfoundation/ethereumjs-rlp@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz#4fee8dc58a53ac6ae87fb1fca7c15dc06c6b5dea" + integrity sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA== -"@nomicfoundation/ethereumjs-statemanager@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz" - integrity sha512-jCtqFjcd2QejtuAMjQzbil/4NHf5aAWxUc+CvS0JclQpl+7M0bxMofR2AJdtz+P3u0ke2euhYREDiE7iSO31vQ== +"@nomicfoundation/ethereumjs-statemanager@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz#3ba4253b29b1211cafe4f9265fee5a0d780976e0" + integrity sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA== dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" - functional-red-black-tree "^1.0.1" + ethers "^5.7.1" + js-sdsl "^4.1.4" -"@nomicfoundation/ethereumjs-trie@^5.0.0": - version "5.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz" - integrity sha512-LIj5XdE+s+t6WSuq/ttegJzZ1vliwg6wlb+Y9f4RlBpuK35B9K02bO7xU+E6Rgg9RGptkWd6TVLdedTI4eNc2A== +"@nomicfoundation/ethereumjs-trie@6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz#9a6dbd28482dca1bc162d12b3733acab8cd12835" + integrity sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ== dependencies: - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + "@types/readable-stream" "^2.3.13" ethereum-cryptography "0.1.3" readable-stream "^3.6.0" -"@nomicfoundation/ethereumjs-tx@^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz" - integrity sha512-Gg3Lir2lNUck43Kp/3x6TfBNwcWC9Z1wYue9Nz3v4xjdcv6oDW9QSMJxqsKw9QEGoBBZ+gqwpW7+F05/rs/g1w== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" +"@nomicfoundation/ethereumjs-tx@5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz#117813b69c0fdc14dd0446698a64be6df71d7e56" + integrity sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g== + dependencies: + "@chainsafe/ssz" "^0.9.2" + "@ethersproject/providers" "^5.7.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-util@^8.0.0": - version "8.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz" - integrity sha512-2emi0NJ/HmTG+CGY58fa+DQuAoroFeSH9gKu9O6JnwTtlzJtgfTixuoOqLEgyyzZVvwfIpRueuePb8TonL1y+A== +"@nomicfoundation/ethereumjs-util@9.0.2": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz#16bdc1bb36f333b8a3559bbb4b17dac805ce904d" + integrity sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ== dependencies: - "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" + "@chainsafe/ssz" "^0.10.0" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" ethereum-cryptography "0.1.3" -"@nomicfoundation/ethereumjs-vm@^6.0.0": - version "6.0.0" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz" - integrity sha512-JMPxvPQ3fzD063Sg3Tp+UdwUkVxMoo1uML6KSzFhMH3hoQi/LMuXBoEHAoW83/vyNS9BxEe6jm6LmT5xdeEJ6w== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@types/async-eventemitter" "^0.2.1" - async-eventemitter "^0.2.4" +"@nomicfoundation/ethereumjs-vm@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz#3b0852cb3584df0e18c182d0672a3596c9ca95e6" + integrity sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA== + dependencies: + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-blockchain" "7.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-evm" "2.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-statemanager" "2.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" debug "^4.3.3" ethereum-cryptography "0.1.3" - functional-red-black-tree "^1.0.1" mcl-wasm "^0.7.1" rustbn.js "~0.2.0" @@ -1983,11 +2073,6 @@ dependencies: fs-extra "^9.1.0" -"@types/async-eventemitter@^0.2.1": - version "0.2.1" - resolved "https://registry.npmjs.org/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz" - integrity sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg== - "@types/bignumber.js@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@types/bignumber.js/-/bignumber.js-5.0.0.tgz#d9f1a378509f3010a3255e9cc822ad0eeb4ab969" @@ -2137,6 +2222,14 @@ resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== +"@types/readable-stream@^2.3.13": + version "2.3.15" + resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.15.tgz#3d79c9ceb1b6a57d5f6e6976f489b9b5384321ae" + integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== + dependencies: + "@types/node" "*" + safe-buffer "~5.1.1" + "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" @@ -2262,6 +2355,41 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@wry/caches@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@wry/caches/-/caches-1.0.1.tgz#8641fd3b6e09230b86ce8b93558d44cf1ece7e52" + integrity sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA== + dependencies: + tslib "^2.3.0" + +"@wry/context@^0.7.0": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.7.4.tgz#e32d750fa075955c4ab2cfb8c48095e1d42d5990" + integrity sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ== + dependencies: + tslib "^2.3.0" + +"@wry/equality@^0.5.6": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.7.tgz#72ec1a73760943d439d56b7b1e9985aec5d497bb" + integrity sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.4.3.tgz#077d52c22365871bf3ffcbab8e95cb8bc5689af4" + integrity sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.5.0.tgz#11e783f3a53f6e4cd1d42d2d1323f5bc3fa99c94" + integrity sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA== + dependencies: + tslib "^2.3.0" + JSONStream@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" @@ -2280,13 +2408,6 @@ abbrev@1.0.x: resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz" integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q== -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - abortcontroller-polyfill@^1.7.3: version "1.7.5" resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" @@ -2383,6 +2504,13 @@ amdefine@>=0.0.4: resolved "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz" integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + ansi-colors@3.2.3: version "3.2.3" resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz" @@ -2629,13 +2757,6 @@ astral-regex@^2.0.0: resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async-eventemitter@^0.2.4: - version "0.2.4" - resolved "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== - dependencies: - async "^2.4.0" - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz" @@ -2646,13 +2767,6 @@ async@1.x: resolved "https://registry.npmjs.org/async/-/async-1.5.2.tgz" integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== -async@^2.4.0: - version "2.6.3" - resolved "https://registry.npmjs.org/async/-/async-2.6.3.tgz" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" @@ -2836,6 +2950,20 @@ boolbase@^1.0.0: resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" @@ -3123,11 +3251,16 @@ camelcase@^5.0.0: resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: +camelcase@^6.0.0, camelcase@^6.2.0: version "6.3.0" resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== +case@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9" + integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== + caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" @@ -3343,6 +3476,11 @@ clean-stack@^2.0.0: resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz" @@ -3712,6 +3850,11 @@ crypto-js@^3.1.9-1: resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.3.0.tgz#846dd1cce2f68aacfa156c8578f926a609b7976b" integrity sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q== +crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + css-select@^4.1.3: version "4.2.1" resolved "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz" @@ -4935,11 +5078,6 @@ ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - eventemitter3@4.0.4: version "4.0.4" resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz" @@ -5772,6 +5910,13 @@ graphql-request@^3.6.1: extract-files "^9.0.0" form-data "^3.0.0" +graphql-tag@^2.12.6: + version "2.12.6" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" + integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== + dependencies: + tslib "^2.1.0" + graphql@^15.7.1: version "15.8.0" resolved "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz" @@ -5853,31 +5998,31 @@ hardhat-spdx-license-identifier@2.0.3: resolved "https://registry.npmjs.org/hardhat-spdx-license-identifier/-/hardhat-spdx-license-identifier-2.0.3.tgz" integrity sha512-G4u4I1md0tWaitX6Os7Nq9sYZ/CFdR+ibm7clCksGJ4yrtdHEZxgLjWpJ0WiALF9SoFKt03PwCe9lczDQ/5ADA== -hardhat@^2.12.6: - version "2.12.6" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.6.tgz#ea3c058bbd81850867389d10f76037cfa52a0019" - integrity sha512-0Ent1O5DsPgvaVb5sxEgsQ3bJRt/Ex92tsoO+xjoNH2Qc4bFmhI5/CHVlFikulalxOPjNmw5XQ2vJFuVQFESAA== +hardhat@^2.19.4: + version "2.19.5" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.19.5.tgz#6017c35ae2844b669e9bcc84c3d05346d4ef031c" + integrity sha512-vx8R7zWCYVgM56vA6o0Wqx2bIIptkN4TMs9QwDqZVNGRhMzBfzqUeEYbp+69gxWp1neg2V2nYQUaaUv7aom1kw== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@nomicfoundation/ethereumjs-vm" "^6.0.0" + "@nomicfoundation/ethereumjs-block" "5.0.2" + "@nomicfoundation/ethereumjs-blockchain" "7.0.2" + "@nomicfoundation/ethereumjs-common" "4.0.2" + "@nomicfoundation/ethereumjs-evm" "2.0.2" + "@nomicfoundation/ethereumjs-rlp" "5.0.2" + "@nomicfoundation/ethereumjs-statemanager" "2.0.2" + "@nomicfoundation/ethereumjs-trie" "6.0.2" + "@nomicfoundation/ethereumjs-tx" "5.0.2" + "@nomicfoundation/ethereumjs-util" "9.0.2" + "@nomicfoundation/ethereumjs-vm" "7.0.2" "@nomicfoundation/solidity-analyzer" "^0.1.0" "@sentry/node" "^5.18.1" "@types/bn.js" "^5.1.0" "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" adm-zip "^0.4.16" aggregate-error "^3.0.0" ansi-escapes "^4.3.0" + boxen "^5.1.2" chalk "^2.4.2" chokidar "^3.4.0" ci-info "^2.0.0" @@ -5897,7 +6042,6 @@ hardhat@^2.12.6: mnemonist "^0.38.0" mocha "^10.0.0" p-map "^4.0.0" - qs "^6.7.0" raw-body "^2.4.1" resolve "1.17.0" semver "^6.3.0" @@ -6056,6 +6200,13 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" @@ -6598,6 +6749,11 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +js-sdsl@^4.1.4: + version "4.4.2" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.2.tgz#2e3c031b1f47d3aca8b775532e3ebb0818e7f847" + integrity sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w== + js-sha3@0.5.5: version "0.5.5" resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz" @@ -6613,9 +6769,9 @@ js-sha3@0.8.0, js-sha3@^0.8.0: resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@3.13.1: @@ -6945,6 +7101,13 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + loupe@^2.3.1: version "2.3.4" resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz" @@ -7067,14 +7230,14 @@ merkletreejs@0.2.32: treeify "^1.1.0" web3-utils "^1.3.4" -merkletreejs@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.3.9.tgz#cdb364a3b974a44f4eff3446522d7066e0cf95de" - integrity sha512-NjlATjJr4NEn9s8v/VEHhgwRWaE1eA/Une07d9SEqKzULJi1Wsh0Y3svwJdP2bYLMmgSBHzOrNydMWM1NN9VeQ== +merkletreejs@^0.3.10: + version "0.3.11" + resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.3.11.tgz#e0de05c3ca1fd368de05a12cb8efb954ef6fc04f" + integrity sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ== dependencies: bignumber.js "^9.0.1" buffer-reverse "^1.0.1" - crypto-js "^3.1.9-1" + crypto-js "^4.2.0" treeify "^1.1.0" web3-utils "^1.3.4" @@ -7731,6 +7894,16 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +optimism@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.0.tgz#e7bb38b24715f3fdad8a9a7fc18e999144bbfa63" + integrity sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ== + dependencies: + "@wry/caches" "^1.0.0" + "@wry/context" "^0.7.0" + "@wry/trie" "^0.4.3" + tslib "^2.3.0" + optionator@^0.8.1, optionator@^0.8.2: version "0.8.3" resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" @@ -8154,6 +8327,15 @@ promise@^8.0.0: dependencies: asap "~2.0.6" +prop-types@^15.7.2: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + proper-lockfile@^4.1.1: version "4.1.2" resolved "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz" @@ -8229,7 +8411,7 @@ qs@6.9.7: resolved "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz" integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== -qs@^6.4.0, qs@^6.7.0, qs@^6.9.4: +qs@^6.4.0, qs@^6.9.4: version "6.10.3" resolved "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz" integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== @@ -8305,6 +8487,11 @@ raw-body@^2.4.1: iconv-lite "0.4.24" unpipe "1.0.0" +react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz" @@ -8411,6 +8598,11 @@ regexpp@^3.0.0: resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +rehackt@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.0.3.tgz#1ea454620d4641db8342e2db44595cf0e7ac6aa0" + integrity sha512-aBRHudKhOWwsTvCbSoinzq+Lej/7R8e8UoPvLZo5HirZIIBLGAgdG7SL9QpdcBoQ7+3QYPi3lRLknAzXBlhZ7g== + req-cwd@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz" @@ -8556,6 +8748,11 @@ resolve@^1.22.2, resolve@^1.22.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +response-iterator@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/response-iterator/-/response-iterator-0.2.6.tgz#249005fb14d2e4eeb478a3f735a28fd8b4c9f3da" + integrity sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw== + responselike@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" @@ -9253,7 +9450,7 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -9451,6 +9648,11 @@ swarm-js@^0.1.40: tar "^4.0.2" xhr-request "^1.0.1" +symbol-observable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" + integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== + sync-request@^6.0.0: version "6.1.0" resolved "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz" @@ -9671,6 +9873,13 @@ ts-essentials@^7.0.1: resolved "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz" integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== +ts-invariant@^0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c" + integrity sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ== + dependencies: + tslib "^2.1.0" + ts-node@10.1.0: version "10.1.0" resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz" @@ -9702,6 +9911,11 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.1.0, tslib@^2.3.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tslib@^2.2.0: version "2.3.1" resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" @@ -11077,6 +11291,13 @@ wide-align@1.1.3: dependencies: string-width "^1.0.2 || 2" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + window-size@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz" @@ -11366,6 +11587,18 @@ yocto-queue@^0.1.0: resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zen-observable-ts@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58" + integrity sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg== + dependencies: + zen-observable "0.8.15" + +zen-observable@0.8.15: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== + zksync-web3@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" From 8a0a3b89170fb19d1c49b130b74e150dd190330a Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Wed, 31 Jan 2024 15:59:15 +0100 Subject: [PATCH 4/5] feat: checks on top --- contracts/Distributor.sol | 2 +- contracts/deprecated/OldDistributor.sol | 2 +- hardhat.config.ts | 8 ++--- .../upgradeDistributionCreator.ts | 35 ++++++++++--------- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/contracts/Distributor.sol b/contracts/Distributor.sol index 1599e54..876c87f 100644 --- a/contracts/Distributor.sol +++ b/contracts/Distributor.sol @@ -58,7 +58,7 @@ struct Claim { } /// @title Distributor -/// @notice Allows LPs on AMMs with concentrated liquidity to claim the rewards that were distributed to them +/// @notice Allows to claim rewards distributed to them through Merkl /// @author Angle Labs. Inc contract Distributor is UUPSHelper { using SafeERC20 for IERC20; diff --git a/contracts/deprecated/OldDistributor.sol b/contracts/deprecated/OldDistributor.sol index 1bd2a9b..9afff90 100644 --- a/contracts/deprecated/OldDistributor.sol +++ b/contracts/deprecated/OldDistributor.sol @@ -60,7 +60,7 @@ struct Claim { /// @title Distributor /// @notice Allows LPs on AMMs with concentrated liquidity to claim the rewards that were distributed to them /// @author Angle Labs. Inc -contract Distributor is UUPSHelper { +contract OldDistributor is UUPSHelper { using SafeERC20 for IERC20; /// @notice Epoch duration diff --git a/hardhat.config.ts b/hardhat.config.ts index b9b1e8a..85f4b6f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -88,11 +88,9 @@ const config: HardhatUserConfig = { hardfork: 'london', forking: { enabled: argv.fork || false, - /* // Mainnet url: nodeUrl('fork'), - blockNumber: 16671190, - */ + blockNumber: 19127150, // Polygon /* url: nodeUrl('forkpolygon'), @@ -116,8 +114,10 @@ const config: HardhatUserConfig = { url: nodeUrl('polygonzkevm'), blockNumber: 3214816, */ + /* url: nodeUrl('linea'), - // blockNumber: 14188687, + blockNumber: 14188687, + */ }, mining: argv.disableAutoMining ? { diff --git a/scripts/mainnet-fork/upgradeDistributionCreator.ts b/scripts/mainnet-fork/upgradeDistributionCreator.ts index 61864dc..58f2469 100644 --- a/scripts/mainnet-fork/upgradeDistributionCreator.ts +++ b/scripts/mainnet-fork/upgradeDistributionCreator.ts @@ -6,12 +6,9 @@ import { deployUpgradeableUUPS, increaseTime, ZERO_ADDRESS } from '../../test/ha import { DistributionCreator, DistributionCreator__factory, + Distributor, + Distributor__factory, ERC20, - ERC20__factory, - MockMerklGaugeMiddleman, - MockMerklGaugeMiddleman__factory, - ProxyAdmin, - ProxyAdmin__factory, } from '../../typechain'; import { formatAmount, parseAmount } from '../../utils/bignumber'; @@ -19,8 +16,7 @@ const argv = yargs.env('').boolean('ci').parseSync(); async function main() { let manager: DistributionCreator; - let middleman: MockMerklGaugeMiddleman; - let angle: ERC20; + let distributor: Distributor; let params: any; const { deploy } = deployments; @@ -35,30 +31,37 @@ async function main() { await network.provider.send('hardhat_setBalance', [governor, '0x10000000000000000000000000000']); const governorSigner = await ethers.provider.getSigner(governor); - const distributorAddress = registry(ChainId.MAINNET)?.Merkl?.DistributionCreator!; + const distributionAddress = registry(ChainId.MAINNET)?.Merkl?.DistributionCreator!; + const distributorAddress = registry(ChainId.MAINNET)?.Merkl?.Distributor!; manager = new ethers.Contract( - distributorAddress, + distributionAddress, DistributionCreator__factory.createInterface(), governorSigner, ) as DistributionCreator; + distributor = new ethers.Contract( + distributorAddress, + Distributor__factory.createInterface(), + governorSigner, + ) as Distributor; + const newImplementation = await new DistributionCreator__factory(deployer).deploy(); await manager.connect(governorSigner).upgradeTo(newImplementation.address); console.log(await manager.core()); console.log(await manager.distributor()); console.log(await manager.feeRecipient()); - console.log(await manager.defaultFees()); + console.log((await manager.defaultFees()).toString()); console.log(await manager.message()); console.log(await manager.distributionList(10)); - console.log(await manager.feeRebate(governor)); - console.log(await manager.isWhitelistedToken(registry(ChainId.MAINNET)?.agEUR?.AgToken!)); - console.log(await manager._nonces('0xfda462548ce04282f4b6d6619823a7c64fdc0185')); - console.log(await manager.userSignatureWhitelist('0xfda462548ce04282f4b6d6619823a7c64fdc0185')); + console.log((await manager.feeRebate(governor)).toString()); + console.log((await manager.isWhitelistedToken(registry(ChainId.MAINNET)?.agEUR?.AgToken!)).toString()); + console.log((await manager._nonces('0xfda462548ce04282f4b6d6619823a7c64fdc0185')).toString()); + console.log((await manager.userSignatureWhitelist('0xfda462548ce04282f4b6d6619823a7c64fdc0185')).toString()); console.log(await manager.rewardTokens(0)); - console.log(await manager.campaignList(0)); - console.log(await manager.campaignSpecificFees(0)); + // console.log(await manager.campaignList(0)); + console.log((await manager.campaignSpecificFees(0)).toString()); } main().catch(error => { From 34f222b25c3a883ada5f63029f2f61520e0ac3f0 Mon Sep 17 00:00:00 2001 From: Pablo Veyrat Date: Wed, 31 Jan 2024 16:26:44 +0100 Subject: [PATCH 5/5] feat: last tests --- scripts/mainnet-fork/upgradeDistributionCreator.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/mainnet-fork/upgradeDistributionCreator.ts b/scripts/mainnet-fork/upgradeDistributionCreator.ts index 58f2469..6176d9c 100644 --- a/scripts/mainnet-fork/upgradeDistributionCreator.ts +++ b/scripts/mainnet-fork/upgradeDistributionCreator.ts @@ -48,6 +48,8 @@ async function main() { const newImplementation = await new DistributionCreator__factory(deployer).deploy(); await manager.connect(governorSigner).upgradeTo(newImplementation.address); + const newDistribImplementation = await new Distributor__factory(deployer).deploy(); + await distributor.connect(governorSigner).upgradeTo(newDistribImplementation.address); console.log(await manager.core()); console.log(await manager.distributor()); @@ -62,6 +64,15 @@ async function main() { console.log(await manager.rewardTokens(0)); // console.log(await manager.campaignList(0)); console.log((await manager.campaignSpecificFees(0)).toString()); + + console.log(await distributor.tree()); + console.log(await distributor.lastTree()); + console.log(await distributor.disputeToken()); + console.log(await distributor.core()); + console.log(await distributor.disputer()); + console.log((await distributor.endOfDisputePeriod()).toString()); + console.log((await distributor.disputePeriod()).toString()); + console.log((await distributor.disputeAmount()).toString()); } main().catch(error => {