From a7f5aefa5acec73a3835822c307db1e730f1da16 Mon Sep 17 00:00:00 2001 From: Kaspar Kallas Date: Tue, 17 Sep 2024 14:41:28 +0300 Subject: [PATCH 1/3] [AUTOMATIONS-CONTRACT] Extended Vesting Scheduler Tests (no unsigned commits) (#2002) * no-op to create pr * additional vesting scheduler tests by 0xPilou * force super token type * test _getSender * test whether superapp * fix fuzz tests (by Pierre) --------- Co-authored-by: Miao ZhiCheng --- .../automation-contracts/scheduler/README.md | 3 +- .../VestingSchedulerV2.StatefulFuzz.t.sol | 433 ++++++++++++++++++ .../scheduler/test/VestingSchedulerV2.t.sol | 157 ++++++- 3 files changed, 590 insertions(+), 3 deletions(-) create mode 100644 packages/automation-contracts/scheduler/test/VestingSchedulerV2.StatefulFuzz.t.sol diff --git a/packages/automation-contracts/scheduler/README.md b/packages/automation-contracts/scheduler/README.md index 9eea2417da..3c5a895cef 100644 --- a/packages/automation-contracts/scheduler/README.md +++ b/packages/automation-contracts/scheduler/README.md @@ -8,8 +8,7 @@ If you have an intended end date and/or start date for a stream, instead of havi ## Vesting Scheduler -The Vesting Scheduler allows you to schedule the vesting of tokens to a receiver account. The Vesting Scheduler does not hold the tokens, rather it simply uses permissions to move them for you - +The Vesting Scheduler allows you to schedule the vesting of tokens to a receiver account. The Vesting Scheduler does not hold the tokens, rather it simply uses permissions to move them for you. ## Getting Started diff --git a/packages/automation-contracts/scheduler/test/VestingSchedulerV2.StatefulFuzz.t.sol b/packages/automation-contracts/scheduler/test/VestingSchedulerV2.StatefulFuzz.t.sol new file mode 100644 index 0000000000..62ffa95dc2 --- /dev/null +++ b/packages/automation-contracts/scheduler/test/VestingSchedulerV2.StatefulFuzz.t.sol @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {ISuperToken} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperToken.sol"; +import {FlowOperatorDefinitions} from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; +import {IVestingSchedulerV2} from "./../contracts/interface/IVestingSchedulerV2.sol"; +import {VestingSchedulerV2} from "./../contracts/VestingSchedulerV2.sol"; +import {FoundrySuperfluidTester} from "@superfluid-finance/ethereum-contracts/test/foundry/FoundrySuperfluidTester.sol"; +import {SuperTokenV1Library} from "@superfluid-finance/ethereum-contracts/contracts/apps/SuperTokenV1Library.sol"; +import "forge-std/console2.sol"; + +/// @title VestingSchedulerTests +contract VestingSchedulerV2StatefulFuzzTests is FoundrySuperfluidTester { + using SuperTokenV1Library for ISuperToken; + + /// @dev This is required by solidity for using the SuperTokenV1Library in the tester + VestingSchedulerV2 public vestingScheduler; + + /// @dev Constants for Testing + uint256 constant MIN_CLIFF_AMOUNT = 2; + uint256 constant MAX_CLIFF_AMOUNT = 1_000e18; + int96 constant MIN_FLOW_RATE = 1; + int96 constant MAX_FLOW_RATE = 1_000e18; + bytes constant EMPTY_CTX = ""; + + uint8 constant numOfTesters = 5; + + constructor() FoundrySuperfluidTester(numOfTesters) { + vestingScheduler = new VestingSchedulerV2(sf.host); + } + + /// SETUP AND HELPERS + function setUp() public virtual override { + vm.setEnv(TOKEN_TYPE_ENV_KEY, "WRAPPER_SUPER_TOKEN"); + super.setUp(); + } + + enum TestActionType { + TA_CREATE_SCHEDULE, + TA_UPDATE_SCHEDULE, + TA_DELETE_SCHEDULE, + TA_EXECUTE_SCHEDULE, + TA_TERMINATE_SCHEDULE + // TA_CREATE_CLAIMABLE_SCHEDULE, + } + + struct Actions { + uint8 actionCode; + uint256 testerId; + address receiver; + uint32 startDate; + uint32 cliffDate; + int96 flowRate; + uint256 cliffAmount; + uint32 endDate; + uint32 newEndDate; + } + + function toActionType( + uint8 actionCode, + uint8 maxAction + ) internal pure returns (TestActionType) { + return TestActionType(actionCode % maxAction); + } + + function test_StatefulFuzz(Actions[10] calldata actions) external { + for (uint256 i = 0; i < actions.length; i++) { + console2.log("ITERATION ID : %d", i); + Actions memory a = actions[i]; + TestActionType t = toActionType(a.actionCode, 5); + + a.testerId = bound(a.testerId, 0, 4); + address sender = TEST_ACCOUNTS[a.testerId]; + + vm.assume( + vestingScheduler + .getVestingSchedule(address(superToken), sender, a.receiver) + .flowRate == 0 + ); + + vm.assume(a.receiver != address(0) && sender != a.receiver); + a.flowRate = int96(bound(a.flowRate, 1, 1000e18)); + a.startDate = uint32( + bound( + a.startDate, + uint32(block.timestamp), + uint32(block.timestamp + 3650 days) + ) + ); + a.endDate = uint32( + bound( + a.endDate, + a.startDate + vestingScheduler.MIN_VESTING_DURATION() + 1, + a.startDate + uint32(3650 days) + ) + ); + if (a.cliffDate == 0) { + a.cliffAmount = 0; + vm.assume(a.startDate < a.endDate); + vm.assume( + a.startDate + vestingScheduler.START_DATE_VALID_AFTER() < + a.endDate - vestingScheduler.END_DATE_VALID_BEFORE() + ); + } else { + a.cliffAmount = bound(a.cliffAmount, 1e18, 1000e18); + a.cliffDate = uint32( + bound(a.cliffDate, a.startDate, a.endDate - 1) + ); + vm.assume( + a.endDate - a.cliffDate > + vestingScheduler.MIN_VESTING_DURATION() + ); + vm.assume( + a.cliffDate + vestingScheduler.START_DATE_VALID_AFTER() < + a.endDate - vestingScheduler.END_DATE_VALID_BEFORE() + ); + } + + if (t == TestActionType.TA_CREATE_SCHEDULE) { + _test_createVestingSchedule( + sender, + a.receiver, + a.startDate, + a.cliffDate, + a.flowRate, + a.cliffAmount, + a.endDate + ); + } else if (t == TestActionType.TA_UPDATE_SCHEDULE) { + _test_updateVestingSchedule( + sender, + a.receiver, + a.startDate, + a.cliffDate, + a.flowRate, + a.cliffAmount, + a.endDate, + a.newEndDate + ); + } else if (t == TestActionType.TA_DELETE_SCHEDULE) { + _test_deleteVestingSchedule( + sender, + a.receiver, + a.startDate, + a.cliffDate, + a.flowRate, + a.cliffAmount, + a.endDate + ); + } else if (t == TestActionType.TA_EXECUTE_SCHEDULE) { + _test_executeCliffAndFlow( + sender, + a.receiver, + a.startDate, + a.cliffDate, + a.flowRate, + a.cliffAmount, + a.endDate + ); + } else if (t == TestActionType.TA_TERMINATE_SCHEDULE) { + _test_executeEndVesting( + sender, + a.receiver, + a.startDate, + a.cliffDate, + a.flowRate, + a.cliffAmount, + a.endDate + ); + } else assert(false); + } + } + + function _test_createVestingSchedule( + address sender, + address receiver, + uint32 startDate, + uint32 cliffDate, + int96 flowRate, + uint256 cliffAmount, + uint32 endDate + ) internal { + _createVestingSchedule( + sender, + receiver, + startDate, + cliffDate, + flowRate, + cliffAmount, + endDate + ); + + //assert storage data + VestingSchedulerV2.VestingSchedule memory schedule = vestingScheduler + .getVestingSchedule(address(superToken), sender, receiver); + + uint32 cliffAndFlowDate = cliffDate == 0 ? startDate : cliffDate; + assertTrue( + schedule.cliffAndFlowDate == cliffAndFlowDate, + "schedule.cliffAndFlowDate" + ); + assertTrue(schedule.endDate == endDate, "schedule.endDate"); + assertTrue(schedule.flowRate == flowRate, "schedule.flowRate"); + assertTrue(schedule.cliffAmount == cliffAmount, "schedule.cliffAmount"); + assertTrue( + schedule.claimValidityDate == 0, + "schedule.claimValidityDate" + ); + } + + function _test_executeCliffAndFlow( + address sender, + address receiver, + uint32 startDate, + uint32 cliffDate, + int96 flowRate, + uint256 cliffAmount, + uint32 endDate + ) internal { + _createVestingSchedule( + sender, + receiver, + startDate, + cliffDate, + flowRate, + cliffAmount, + endDate + ); + + _provisionSender(sender); + _arrangeAllowances(sender, flowRate); + + // Set the time to 1 second after the cliff and flow date + vm.warp(cliffDate == 0 ? startDate + 1 : cliffDate + 1); + + bool success = vestingScheduler.executeCliffAndFlow( + superToken, + sender, + receiver + ); + + assertTrue(success, "executeCliffAndFlow should return true"); + + //assert storage data + VestingSchedulerV2.VestingSchedule memory schedule = vestingScheduler + .getVestingSchedule(address(superToken), sender, receiver); + assertTrue(schedule.cliffAndFlowDate == 0, "schedule.cliffAndFlowDate"); + assertTrue(schedule.cliffAmount == 0, "schedule.cliffAmount"); + } + + function _test_updateVestingSchedule( + address sender, + address receiver, + uint32 startDate, + uint32 cliffDate, + int96 flowRate, + uint256 cliffAmount, + uint32 endDate, + uint32 newEndDate + ) internal { + _createVestingSchedule( + sender, + receiver, + startDate, + cliffDate, + flowRate, + cliffAmount, + endDate + ); + + _provisionSender(sender); + _arrangeAllowances(sender, flowRate); + + // Set the time to 1 second after the cliff and flow date + vm.warp(cliffDate == 0 ? startDate + 1 : cliffDate + 1); + vestingScheduler.executeCliffAndFlow(superToken, sender, receiver); + + vm.assume(newEndDate > block.timestamp); + vm.prank(sender); + vestingScheduler.updateVestingSchedule( + superToken, + receiver, + newEndDate, + EMPTY_CTX + ); + + //assert storage data + VestingSchedulerV2.VestingSchedule memory schedule = vestingScheduler + .getVestingSchedule(address(superToken), sender, receiver); + assertTrue(schedule.endDate == newEndDate, "schedule.cliffAndFlowDate"); + assertTrue(schedule.remainderAmount == 0, "schedule.remainderAmount"); + } + + function _test_executeEndVesting( + address sender, + address receiver, + uint32 startDate, + uint32 cliffDate, + int96 flowRate, + uint256 cliffAmount, + uint32 endDate + ) internal { + _createVestingSchedule( + sender, + receiver, + startDate, + cliffDate, + flowRate, + cliffAmount, + endDate + ); + + _provisionSender(sender); + _arrangeAllowances(sender, flowRate); + + // Set the time to 1 second after the cliff and flow date + vm.warp(cliffDate == 0 ? startDate + 1 : cliffDate + 1); + + vestingScheduler.executeCliffAndFlow(superToken, sender, receiver); + + vm.warp(endDate - vestingScheduler.END_DATE_VALID_BEFORE() + 1); + + bool success = vestingScheduler.executeEndVesting( + superToken, + sender, + receiver + ); + assertTrue(success, "executeEndVesting should return true"); + + //assert storage data + VestingSchedulerV2.VestingSchedule memory schedule = vestingScheduler + .getVestingSchedule(address(superToken), sender, receiver); + assertTrue(schedule.cliffAndFlowDate == 0, "schedule.cliffAndFlowDate"); + assertTrue(schedule.endDate == 0, "schedule.endDate"); + assertTrue(schedule.flowRate == 0, "schedule.flowRate"); + assertTrue(schedule.cliffAmount == 0, "schedule.cliffAmount"); + assertTrue( + schedule.claimValidityDate == 0, + "schedule.claimValidityDate" + ); + assertTrue(schedule.remainderAmount == 0, "schedule.remainderAmount"); + } + + function _test_deleteVestingSchedule( + address sender, + address receiver, + uint32 startDate, + uint32 cliffDate, + int96 flowRate, + uint256 cliffAmount, + uint32 endDate + ) internal { + _createVestingSchedule( + sender, + receiver, + startDate, + cliffDate, + flowRate, + cliffAmount, + endDate + ); + + vm.prank(sender); + vestingScheduler.deleteVestingSchedule(superToken, receiver, EMPTY_CTX); + + //assert storage data + VestingSchedulerV2.VestingSchedule memory schedule = vestingScheduler + .getVestingSchedule(address(superToken), sender, receiver); + assertTrue(schedule.cliffAndFlowDate == 0, "schedule.cliffAndFlowDate"); + assertTrue(schedule.endDate == 0, "schedule.endDate"); + assertTrue(schedule.flowRate == 0, "schedule.flowRate"); + assertTrue(schedule.cliffAmount == 0, "schedule.cliffAmount"); + assertTrue( + schedule.claimValidityDate == 0, + "schedule.claimValidityDate" + ); + assertTrue(schedule.remainderAmount == 0, "schedule.remainderAmount"); + } + + function _createVestingSchedule( + address sender, + address receiver, + uint32 startDate, + uint32 cliffDate, + int96 flowRate, + uint256 cliffAmount, + uint32 endDate + ) private { + vm.prank(sender); + vestingScheduler.createVestingSchedule( + superToken, + receiver, + startDate, + cliffDate, + flowRate, + cliffAmount, + endDate, + 0, + EMPTY_CTX + ); + } + + function _provisionSender(address sender) private { + token.mint(sender, INIT_TOKEN_BALANCE); + vm.startPrank(sender); + token.approve(address(superToken), INIT_TOKEN_BALANCE); + superToken.upgrade(INIT_TOKEN_BALANCE); + vm.stopPrank(); + } + + function _arrangeAllowances(address sender, int96 flowRate) private { + vm.startPrank(sender); + // ## Superfluid ACL allowance and permissions + sf.host.callAgreement( + sf.cfa, + abi.encodeCall( + sf.cfa.updateFlowOperatorPermissions, + ( + superToken, + address(vestingScheduler), + FlowOperatorDefinitions.AUTHORIZE_FULL_CONTROL, + flowRate, + new bytes(0) + ) + ), + new bytes(0) + ); + + // ## ERC-20 allowance for cliff and compensation transfers + superToken.approve(address(vestingScheduler), type(uint256).max); + vm.stopPrank(); + } +} \ No newline at end of file diff --git a/packages/automation-contracts/scheduler/test/VestingSchedulerV2.t.sol b/packages/automation-contracts/scheduler/test/VestingSchedulerV2.t.sol index 1dd9086899..888f58d7df 100644 --- a/packages/automation-contracts/scheduler/test/VestingSchedulerV2.t.sol +++ b/packages/automation-contracts/scheduler/test/VestingSchedulerV2.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import { ISuperToken } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperToken.sol"; -import { FlowOperatorDefinitions } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; +import { FlowOperatorDefinitions, ISuperfluid, BatchOperation, ISuperApp } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; import { IVestingSchedulerV2 } from "./../contracts/interface/IVestingSchedulerV2.sol"; import { VestingSchedulerV2 } from "./../contracts/VestingSchedulerV2.sol"; import { FoundrySuperfluidTester } from "@superfluid-finance/ethereum-contracts/test/foundry/FoundrySuperfluidTester.sol"; @@ -91,6 +91,7 @@ contract VestingSchedulerV2Tests is FoundrySuperfluidTester { uint32 immutable CLAIM_VALIDITY_DATE = uint32(BLOCK_TIMESTAMP + 15 days); uint32 immutable END_DATE = uint32(BLOCK_TIMESTAMP + 20 days); bytes constant EMPTY_CTX = ""; + bytes constant NON_EMPTY_CTX = abi.encode(alice); uint256 internal _expectedTotalSupply = 0; constructor() FoundrySuperfluidTester(3) { @@ -276,7 +277,37 @@ contract VestingSchedulerV2Tests is FoundrySuperfluidTester { /// TESTS + function test_vesting_scheduler_is_superapp() public { + assertTrue(sf.host.isApp(ISuperApp(address(new VestingSchedulerV2(sf.host))))); + } + function testCreateVestingSchedule() public { + vm.expectEmit(true, true, true, true); + emit VestingScheduleCreated( + superToken, alice, bob, START_DATE, CLIFF_DATE, FLOW_RATE, END_DATE, CLIFF_TRANSFER_AMOUNT, 0, 0); + + vm.startPrank(alice); + vestingScheduler.createVestingSchedule( + superToken, + bob, + START_DATE, + CLIFF_DATE, + FLOW_RATE, + CLIFF_TRANSFER_AMOUNT, + END_DATE, + EMPTY_CTX + ); + vm.stopPrank(); + + //assert storage data + VestingSchedulerV2.VestingSchedule memory schedule = vestingScheduler.getVestingSchedule(address(superToken), alice, bob); + assertTrue(schedule.cliffAndFlowDate == CLIFF_DATE , "schedule.cliffAndFlowDate"); + assertTrue(schedule.endDate == END_DATE , "schedule.endDate"); + assertTrue(schedule.flowRate == FLOW_RATE , "schedule.flowRate"); + assertTrue(schedule.cliffAmount == CLIFF_TRANSFER_AMOUNT , "schedule.cliffAmount"); + } + + function test_createVestingSchedule_v1_overload() public { vm.expectEmit(true, true, true, true); emit VestingScheduleCreated( superToken, alice, bob, START_DATE, CLIFF_DATE, FLOW_RATE, END_DATE, CLIFF_TRANSFER_AMOUNT, 0, 0); @@ -1369,6 +1400,66 @@ contract VestingSchedulerV2Tests is FoundrySuperfluidTester { vm.warp(type(uint32).max); assertEq($.afterSenderBalance, superToken.balanceOf(alice), "After the schedule has ended, the sender's balance should never change."); } + + function test_createAndExecuteVestingScheduleFromAmountAndDuration(uint256 _totalAmount, uint32 _totalDuration) public { + + _totalDuration = SafeCast.toUint32(bound(_totalDuration, uint32(7 days), uint32(365 days))); + _totalAmount = bound(_totalAmount, 1 ether, 100 ether); + + int96 flowRate = SafeCast.toInt96( + SafeCast.toInt256(_totalAmount / _totalDuration) + ); + + uint96 remainderAmount = SafeCast.toUint96( + _totalAmount - (SafeCast.toUint256(flowRate) * _totalDuration) + ); + + _setACL_AUTHORIZE_FULL_CONTROL(alice, flowRate); + + vm.startPrank(alice); + superToken.increaseAllowance(address(vestingScheduler), type(uint256).max); + + vm.expectEmit(true, true, true, true); + emit VestingScheduleCreated( + superToken, alice, bob, uint32(block.timestamp), 0, flowRate, uint32(block.timestamp) + _totalDuration, 0, 0, remainderAmount); + + vm.expectEmit(true, true, true, true); + emit VestingCliffAndFlowExecuted(superToken, alice, bob, uint32(block.timestamp), flowRate, 0, 0); + + vestingScheduler.createAndExecuteVestingScheduleFromAmountAndDuration(superToken, bob, _totalAmount, _totalDuration, EMPTY_CTX); + + vm.stopPrank(); + } + + function test_createAndExecuteVestingScheduleFromAmountAndDuration_noCtx(uint256 _totalAmount, uint32 _totalDuration) public { + _totalDuration = SafeCast.toUint32(bound(_totalDuration, uint32(7 days), uint32(365 days))); + _totalAmount = bound(_totalAmount, 1 ether, 100 ether); + + int96 flowRate = SafeCast.toInt96( + SafeCast.toInt256(_totalAmount / _totalDuration) + ); + + uint96 remainderAmount = SafeCast.toUint96( + _totalAmount - (SafeCast.toUint256(flowRate) * _totalDuration) + ); + + _setACL_AUTHORIZE_FULL_CONTROL(alice, flowRate); + + vm.startPrank(alice); + superToken.increaseAllowance(address(vestingScheduler), type(uint256).max); + + vm.expectEmit(true, true, true, true); + emit VestingScheduleCreated( + superToken, alice, bob, uint32(block.timestamp), 0, flowRate, uint32(block.timestamp) + _totalDuration, 0, 0, remainderAmount); + + vm.expectEmit(true, true, true, true); + emit VestingCliffAndFlowExecuted(superToken, alice, bob, uint32(block.timestamp), flowRate, 0, 0); + + vestingScheduler.createAndExecuteVestingScheduleFromAmountAndDuration(superToken, bob, _totalAmount, _totalDuration); + + vm.stopPrank(); + } + function test_createClaimableVestingSchedule() public { @@ -2182,6 +2273,12 @@ contract VestingSchedulerV2Tests is FoundrySuperfluidTester { testAssertScheduleDoesNotExist(address(superToken), alice, bob); } + function test_executeEndVesting_scheduleNotClaimed() public { + _createClaimableVestingScheduleWithDefaultData(alice, bob); + vm.expectRevert(IVestingSchedulerV2.ScheduleNotClaimed.selector); + vestingScheduler.executeEndVesting(superToken, alice, bob); + } + function test_getMaximumNeededTokenAllowance_with_claim_should_end_with_zero_if_extreme_ranges_are_used( uint256 totalAmount, uint32 totalDuration, @@ -2280,4 +2377,62 @@ contract VestingSchedulerV2Tests is FoundrySuperfluidTester { testAssertScheduleDoesNotExist(address(superToken), alice, bob); } + + function test_getSender_throws_when_invalid_host() public { + vm.expectRevert(IVestingSchedulerV2.HostInvalid.selector); + + vm.startPrank(alice); + vestingScheduler.createVestingSchedule( + superToken, + bob, + START_DATE, + CLIFF_DATE, + FLOW_RATE, + CLIFF_TRANSFER_AMOUNT, + END_DATE, + 0, + NON_EMPTY_CTX + ); + vm.stopPrank(); + } + + function test_getSender_works_in_a_batch_call() public { + // Create a vesting schedule to update with a batch call that uses the context + vm.startPrank(alice); + vestingScheduler.createVestingSchedule( + superToken, + bob, + START_DATE, + CLIFF_DATE, + FLOW_RATE, + CLIFF_TRANSFER_AMOUNT, + END_DATE, + 0, + EMPTY_CTX + ); + _arrangeAllowances(alice, FLOW_RATE); + vm.stopPrank(); + + vm.warp(CLIFF_DATE != 0 ? CLIFF_DATE : START_DATE); + vestingScheduler.executeCliffAndFlow(superToken, alice, bob); + + uint32 newEndDate = type(uint32).max - 1234; + + // Setting up a batch call. Superfluid Protocol will replace the emtpy context with data about the sender. That's where the sender is retrieved from. + ISuperfluid.Operation[] memory ops = new ISuperfluid.Operation[](1); + ops[0] = ISuperfluid.Operation({ + operationType: BatchOperation.OPERATION_TYPE_SUPERFLUID_CALL_APP_ACTION, + target: address(vestingScheduler), + data: abi.encodeCall(vestingScheduler.updateVestingSchedule, (superToken, bob, newEndDate, EMPTY_CTX)) + }); + + // Act + vm.prank(alice); + sf.host.batchCall(ops); + vm.stopPrank(); + + // Assert + IVestingSchedulerV2.VestingSchedule memory schedule = vestingScheduler.getVestingSchedule(address(superToken), alice, bob); + assertEq(schedule.endDate, newEndDate); + } } From 4867f38db73d6891de5edb4047cd884259686725 Mon Sep 17 00:00:00 2001 From: Didi Date: Wed, 18 Sep 2024 14:17:18 +0200 Subject: [PATCH 2/3] [ETHEREUM-CONTRACTS] add MacroForwarder to the test deployer and adjust existing tests (#2021) --- packages/ethereum-contracts/CHANGELOG.md | 1 + .../SuperfluidFrameworkDeploymentSteps.sol | 8 +++++ .../foundry/SuperfluidFrameworkDeployer.t.sol | 1 + .../test/foundry/utils/MacroForwarder.t.sol | 34 +++++++------------ 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/ethereum-contracts/CHANGELOG.md b/packages/ethereum-contracts/CHANGELOG.md index eaf48fb06a..61135dd11a 100644 --- a/packages/ethereum-contracts/CHANGELOG.md +++ b/packages/ethereum-contracts/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Changed * `IUserDefinedMacro`: added a method `postCheck()` which allows to verify state changes after running the macro. +* `SuperfluidFrameworkDeployer` now also deploys and `MacroForwarder` and enables it as trusted forwarder. ### Fixed diff --git a/packages/ethereum-contracts/contracts/utils/SuperfluidFrameworkDeploymentSteps.sol b/packages/ethereum-contracts/contracts/utils/SuperfluidFrameworkDeploymentSteps.sol index 7d15408dd4..a8c769b773 100644 --- a/packages/ethereum-contracts/contracts/utils/SuperfluidFrameworkDeploymentSteps.sol +++ b/packages/ethereum-contracts/contracts/utils/SuperfluidFrameworkDeploymentSteps.sol @@ -33,6 +33,7 @@ import { CFAv1Library } from "../apps/CFAv1Library.sol"; import { IDAv1Library } from "../apps/IDAv1Library.sol"; import { IResolver } from "../interfaces/utils/IResolver.sol"; import { DMZForwarder } from "../utils/DMZForwarder.sol"; +import { MacroForwarder } from "../utils/MacroForwarder.sol"; /// @title Superfluid Framework Deployment Steps /// @author Superfluid @@ -66,6 +67,7 @@ contract SuperfluidFrameworkDeploymentSteps { CFAv1Forwarder cfaV1Forwarder; IDAv1Forwarder idaV1Forwarder; GDAv1Forwarder gdaV1Forwarder; + MacroForwarder macroForwarder; BatchLiquidator batchLiquidator; TOGA toga; } @@ -92,6 +94,7 @@ contract SuperfluidFrameworkDeploymentSteps { CFAv1Forwarder internal cfaV1Forwarder; IDAv1Forwarder internal idaV1Forwarder; GDAv1Forwarder internal gdaV1Forwarder; + MacroForwarder internal macroForwarder; // Other Peripheral Contracts TestResolver internal testResolver; @@ -121,6 +124,7 @@ contract SuperfluidFrameworkDeploymentSteps { cfaV1Forwarder: cfaV1Forwarder, idaV1Forwarder: idaV1Forwarder, gdaV1Forwarder: gdaV1Forwarder, + macroForwarder: macroForwarder, batchLiquidator: batchLiquidator, toga: toga }); @@ -224,6 +228,10 @@ contract SuperfluidFrameworkDeploymentSteps { // Deploy GDAv1Forwarder gdaV1Forwarder = GDAv1ForwarderDeployerLibrary.deploy(host); testGovernance.enableTrustedForwarder(host, ISuperfluidToken(address(0)), address(gdaV1Forwarder)); + + // Deploy MacroForwarder + macroForwarder = new MacroForwarder(host); + testGovernance.enableTrustedForwarder(host, ISuperfluidToken(address(0)), address(macroForwarder)); } else if (step == 5) {// PERIPHERAL CONTRACTS: SuperToken Logic and SuperTokenFactory Logic // Deploy canonical SuperToken logic contract superTokenLogic = SuperToken(SuperTokenDeployerLibrary.deploy( diff --git a/packages/ethereum-contracts/test/foundry/SuperfluidFrameworkDeployer.t.sol b/packages/ethereum-contracts/test/foundry/SuperfluidFrameworkDeployer.t.sol index 250b0367f8..abbfc3c1c9 100644 --- a/packages/ethereum-contracts/test/foundry/SuperfluidFrameworkDeployer.t.sol +++ b/packages/ethereum-contracts/test/foundry/SuperfluidFrameworkDeployer.t.sol @@ -21,6 +21,7 @@ contract SuperfluidFrameworkDeployerTest is FoundrySuperfluidTester { assertTrue(address(sf.cfaV1Forwarder) != address(0), "SFDeployer: cfaV1Forwarder not deployed"); assertTrue(address(sf.idaV1Forwarder) != address(0), "SFDeployer: idaV1Forwarder not deployed"); assertTrue(address(sf.gdaV1Forwarder) != address(0), "SFDeployer: gdaV1Forwarder not deployed"); + assertTrue(address(sf.macroForwarder) != address(0), "SFDeployer: macroForwarder not deployed"); assertTrue(address(sf.batchLiquidator) != address(0), "SFDeployer: batchLiquidator not deployed"); } diff --git a/packages/ethereum-contracts/test/foundry/utils/MacroForwarder.t.sol b/packages/ethereum-contracts/test/foundry/utils/MacroForwarder.t.sol index ac72df5219..f4b5d05cda 100644 --- a/packages/ethereum-contracts/test/foundry/utils/MacroForwarder.t.sol +++ b/packages/ethereum-contracts/test/foundry/utils/MacroForwarder.t.sol @@ -74,7 +74,7 @@ contract GoodMacro is IUserDefinedMacro { contract MultiFlowDeleteMacro is IUserDefinedMacro { error InsufficientReward(); - function buildBatchOperations(ISuperfluid host, bytes memory params, address msgSender) external override view + function buildBatchOperations(ISuperfluid host, bytes memory params, address /*msgSender*/) external override view returns (ISuperfluid.Operation[] memory operations) { IConstantFlowAgreementV1 cfa = IConstantFlowAgreementV1(address(host.getAgreementClass( @@ -82,7 +82,7 @@ contract MultiFlowDeleteMacro is IUserDefinedMacro { ))); // parse params - (ISuperToken token, address sender, address[] memory receivers, uint256 minBalanceAfter) = + (ISuperToken token, address sender, address[] memory receivers,) = abi.decode(params, (ISuperToken, address, address[], uint256)); // construct batch operations @@ -110,7 +110,7 @@ contract MultiFlowDeleteMacro is IUserDefinedMacro { return abi.encode(superToken, sender, receivers, minBalanceAfter); } - function postCheck(ISuperfluid host, bytes memory params, address msgSender) external view { + function postCheck(ISuperfluid /*host*/, bytes memory params, address msgSender) external view { // parse params (ISuperToken superToken,,, uint256 minBalanceAfter) = abi.decode(params, (ISuperToken, address, address[], uint256)); @@ -172,29 +172,19 @@ contract StatefulMacro is IUserDefinedMacro { // ============== Test Contract ============== contract MacroForwarderTest is FoundrySuperfluidTester { - MacroForwarder internal macroForwarder; - constructor() FoundrySuperfluidTester(5) { } - function setUp() public override { - super.setUp(); - macroForwarder = new MacroForwarder(sf.host); - vm.startPrank(address(sf.governance.owner())); - sf.governance.enableTrustedForwarder(sf.host, ISuperToken(address(0)), address(macroForwarder)); - vm.stopPrank(); - } - function testDummyMacro() external { NaugthyMacro m = new NaugthyMacro(false /* not naughty */); - macroForwarder.runMacro(IUserDefinedMacro(address(m)), new bytes(0)); + sf.macroForwarder.runMacro(IUserDefinedMacro(address(m)), new bytes(0)); } function testNaugtyMacro() external { NaugthyMacro m = new NaugthyMacro(true /* naughty */); vm.expectRevert(); // Note: need to cast the naughty macro - macroForwarder.runMacro(IUserDefinedMacro(address(m)), new bytes(0)); + sf.macroForwarder.runMacro(IUserDefinedMacro(address(m)), new bytes(0)); } function testGoodMacro() external { @@ -205,7 +195,7 @@ contract MacroForwarderTest is FoundrySuperfluidTester { vm.startPrank(admin); // NOTE! This is different from abi.encode(superToken, int96(42), [bob, carol]), // which is a fixed array: address[2]. - macroForwarder.runMacro(m, abi.encode(superToken, int96(42), recipients)); + sf.macroForwarder.runMacro(m, abi.encode(superToken, int96(42), recipients)); assertEq(sf.cfa.getNetFlow(superToken, bob), 42); assertEq(sf.cfa.getNetFlow(superToken, carol), 42); vm.stopPrank(); @@ -219,7 +209,7 @@ contract MacroForwarderTest is FoundrySuperfluidTester { vm.startPrank(admin); // NOTE! This is different from abi.encode(superToken, int96(42), [bob, carol]), // which is a fixed array: address[2]. - macroForwarder.runMacro(m, m.getParams(superToken, int96(42), recipients)); + sf.macroForwarder.runMacro(m, m.getParams(superToken, int96(42), recipients)); assertEq(sf.cfa.getNetFlow(superToken, bob), 42); assertEq(sf.cfa.getNetFlow(superToken, carol), 42); vm.stopPrank(); @@ -231,10 +221,10 @@ contract MacroForwarderTest is FoundrySuperfluidTester { recipients[1] = carol; StatefulMacro m = new StatefulMacro(); m.setConfig(StatefulMacro.Config( - macroForwarder, superToken, 42, recipients, dan + sf.macroForwarder, superToken, 42, recipients, dan )); vm.startPrank(admin); - macroForwarder.runMacro(m, new bytes(0)); + sf.macroForwarder.runMacro(m, new bytes(0)); assertEq(sf.cfa.getNetFlow(superToken, bob), 42); assertEq(sf.cfa.getNetFlow(superToken, carol), 42); vm.stopPrank(); @@ -254,7 +244,7 @@ contract MacroForwarderTest is FoundrySuperfluidTester { superToken.createFlow(recipients[i], 42); } // now batch-delete them - macroForwarder.runMacro(m, m.getParams(superToken, sender, recipients, 0)); + sf.macroForwarder.runMacro(m, m.getParams(superToken, sender, recipients, 0)); for (uint i = 0; i < recipients.length; ++i) { assertEq(sf.cfa.getNetFlow(superToken, recipients[i]), 0); @@ -284,9 +274,9 @@ contract MacroForwarderTest is FoundrySuperfluidTester { uint256 danBalanceBefore = superToken.balanceOf(dan); // unreasonable reward expectation: post check fails vm.expectRevert(MultiFlowDeleteMacro.InsufficientReward.selector); - macroForwarder.runMacro(m, abi.encode(superToken, alice, recipients, danBalanceBefore + 1e24)); + sf.macroForwarder.runMacro(m, abi.encode(superToken, alice, recipients, danBalanceBefore + 1e24)); // reasonable reward expectation: post check passes - macroForwarder.runMacro(m, abi.encode(superToken, alice, recipients, danBalanceBefore + (uint256(uint96(flowRate)) * 600))); + sf.macroForwarder.runMacro(m, abi.encode(superToken, alice, recipients, danBalanceBefore + (uint256(uint96(flowRate)) * 600))); } } \ No newline at end of file From cc18b23b0aaacfbe50d7d52ce8278a99cee312ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:04:55 +0300 Subject: [PATCH 3/3] Bump express from 4.19.2 to 4.21.0 (#2020) Bumps [express](https://github.com/expressjs/express) from 4.19.2 to 4.21.0. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Miao ZhiCheng --- yarn.lock | 172 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 137 insertions(+), 35 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6d5880bb95..702e3a8236 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6292,7 +6292,25 @@ bn.js@^5.0.0, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@1.20.2, body-parser@^1.16.0, body-parser@^1.19.0: +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.13.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + +body-parser@^1.16.0, body-parser@^1.19.0: version "1.20.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== @@ -6759,6 +6777,17 @@ call-bind@^1.0.4, call-bind@^1.0.5: get-intrinsic "^1.2.1" set-function-length "^1.1.1" +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -8143,6 +8172,15 @@ define-data-property@^1.0.1, define-data-property@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -8557,6 +8595,11 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + encoding-down@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" @@ -8740,6 +8783,18 @@ es-abstract@^1.22.1: unbox-primitive "^1.0.2" which-typed-array "^1.1.13" +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-module-lexer@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f" @@ -9588,36 +9643,36 @@ exponential-backoff@^3.1.1: integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== express@^4.14.0, express@^4.17.1: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + version "4.21.0" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.0.tgz#d57cb706d49623d4ac27833f1cbc466b668eb915" + integrity sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.2" + body-parser "1.20.3" content-disposition "0.5.4" content-type "~1.0.4" cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.2.0" + finalhandler "1.3.1" fresh "0.5.2" http-errors "2.0.0" - merge-descriptors "1.0.1" + merge-descriptors "1.0.3" methods "~1.1.2" on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.7" + path-to-regexp "0.1.10" proxy-addr "~2.0.7" - qs "6.11.0" + qs "6.13.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" + send "0.19.0" + serve-static "1.16.2" setprototypeof "1.2.0" statuses "2.0.1" type-is "~1.6.18" @@ -9859,13 +9914,13 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" on-finished "2.4.1" parseurl "~1.3.3" @@ -10331,6 +10386,17 @@ get-intrinsic@^1.2.2: has-symbols "^1.0.3" hasown "^2.0.0" +get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-iterator@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/get-iterator/-/get-iterator-1.0.2.tgz#cd747c02b4c084461fac14f48f6b45a80ed25c82" @@ -11006,6 +11072,13 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + has-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" @@ -13508,10 +13581,10 @@ meow@^8.1.2: type-fest "^0.18.0" yargs-parser "^20.2.3" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== merge-options@^3.0.4: version "3.0.4" @@ -15343,10 +15416,10 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== path-type@^1.0.0: version "1.1.0" @@ -15977,6 +16050,13 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + qs@^6.4.0, qs@^6.9.4: version "6.11.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" @@ -16870,10 +16950,10 @@ semver@~5.4.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" @@ -16927,15 +17007,15 @@ serialize-javascript@^6.0.2: dependencies: randombytes "^2.1.0" -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.18.0" + send "0.19.0" servify@^0.1.12: version "0.1.12" @@ -16963,6 +17043,18 @@ set-function-length@^1.1.1: gopd "^1.0.1" has-property-descriptors "^1.0.0" +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + set-function-name@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" @@ -17081,6 +17173,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + signal-exit@3.0.7, signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"