From be43dd172d9c4aa68360dd5d6fb8482228939886 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 11 Jul 2024 22:50:31 +0200 Subject: [PATCH 1/4] fix: skip already queued up tx --- src/RoboSaverVirtualModule.sol | 9 +++++++-- src/abstracts/RoboSaverConstants.sol | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/RoboSaverVirtualModule.sol b/src/RoboSaverVirtualModule.sol index 70e1b6f..31fd6ce 100644 --- a/src/RoboSaverVirtualModule.sol +++ b/src/RoboSaverVirtualModule.sol @@ -515,8 +515,13 @@ contract RoboSaverVirtualModule is /// @param _target The address of the target of the transaction /// @param _payload The payload of the transaction function _queueTx(address _target, bytes memory _payload) internal { - /// @dev since all actions go through multicall3, operation is set to 1 (DelegateCall) - delayModule.execTransactionFromModule(_target, 0, _payload, 1); + /// @dev the newest action is leading; if we already have a transaction queued up we should skip it + if (queuedTx.nonce != 0) { + delayModule.setTxNonce(queuedTx.nonce); + delete queuedTx; + } + + delayModule.execTransactionFromModule(_target, 0, _payload, OPERATION_DELEGATECALL); uint256 cachedQueueNonce = delayModule.queueNonce(); queuedTx = VirtualModule.QueuedTx(cachedQueueNonce, _target, _payload); diff --git a/src/abstracts/RoboSaverConstants.sol b/src/abstracts/RoboSaverConstants.sol index f390196..9ca9fb0 100644 --- a/src/abstracts/RoboSaverConstants.sol +++ b/src/abstracts/RoboSaverConstants.sol @@ -14,6 +14,7 @@ abstract contract RoboSaverConstants { uint256 constant EURE_TOKEN_BPT_INDEX = 2; uint256 constant EURE_TOKEN_BPT_INDEX_USER = 1; uint256 constant MODULE_PAGE_SIZE = 1; + uint256 constant OPERATION_DELEGATECALL = 1; address constant MULTICALL3 = 0xcA11bde05977b3631167028862bE2a173976CA11; From 3e69e032e30a61c02d7a7531281e5a9086793b97 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Thu, 11 Jul 2024 22:53:45 +0200 Subject: [PATCH 2/4] fix: operation constant is `uint8` --- src/abstracts/RoboSaverConstants.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/abstracts/RoboSaverConstants.sol b/src/abstracts/RoboSaverConstants.sol index 9ca9fb0..b0a9027 100644 --- a/src/abstracts/RoboSaverConstants.sol +++ b/src/abstracts/RoboSaverConstants.sol @@ -9,12 +9,11 @@ import "@balancer-v2/interfaces/contracts/vault/IVault.sol"; import "@balancer-v2/interfaces/contracts/solidity-utils/misc/IERC4626.sol"; abstract contract RoboSaverConstants { + uint8 constant OPERATION_DELEGATECALL = 1; uint16 constant MAX_BPS = 10_000; - uint256 constant EURE_TOKEN_BPT_INDEX = 2; uint256 constant EURE_TOKEN_BPT_INDEX_USER = 1; uint256 constant MODULE_PAGE_SIZE = 1; - uint256 constant OPERATION_DELEGATECALL = 1; address constant MULTICALL3 = 0xcA11bde05977b3631167028862bE2a173976CA11; From 757718d5e1105df5ed7b0067d61c0511aebd9302 Mon Sep 17 00:00:00 2001 From: Petrovska Date: Wed, 17 Jul 2024 22:08:07 +0900 Subject: [PATCH 3/4] test: cover corner-case scenario always on ci test suite, it should not revert once fixed --- test/regression/CornerCaseV0_1_0Test.t.sol | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/regression/CornerCaseV0_1_0Test.t.sol diff --git a/test/regression/CornerCaseV0_1_0Test.t.sol b/test/regression/CornerCaseV0_1_0Test.t.sol new file mode 100644 index 0000000..388118f --- /dev/null +++ b/test/regression/CornerCaseV0_1_0Test.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.25; + +import {BaseFixture} from "../BaseFixture.sol"; + +import {VirtualModule} from "../../src/types/DataTypes.sol"; + +/// @notice This file is for testing the corner cases that were faced during v0.1.0 tests-run +/// and face minor challenges which should be always fixed and gracefully handled on `>v0.1.0` +contract CornerCaseV0_1_0Test is BaseFixture { + function test_DepositAndShutdownBlockage() public { + // 1. encounter condition where naturally a deposit is being queued + _incomingEure(1_000e18); + uint256 surplus = roboModule.surplus(); + assertGt(surplus, 0); + + _upkeepAndAssertPayload(abi.encode(VirtualModule.PoolAction.DEPOSIT, surplus)); + + (uint256 nonceDepositTx,, bytes memory payloadDepositTx) = roboModule.queuedTx(); + assertEq(nonceDepositTx, 1); + + // 2. admin of the virtual module decides to `shutdown()` while initial queue tx is on cooldown phase still + vm.prank(roboModule.CARD()); + roboModule.shutdown(); + + // 3. Internal payload should not have being override, otherwise initial deposit never can be executed + (uint256 nonceShutdownTx,, bytes memory payloadShutdownTx) = roboModule.queuedTx(); + + // @note if it not identical a blockage will be suffer and force to wait for tx expiration + assertEq(nonceDepositTx, nonceShutdownTx); + assertEq(payloadDepositTx, payloadShutdownTx); + + } +} From 566e425d7960ede02b0d396c0ed95375a1600c25 Mon Sep 17 00:00:00 2001 From: petrovska-petro Date: Wed, 17 Jul 2024 13:10:03 +0000 Subject: [PATCH 4/4] style: ci lint `forge fmt` --- test/regression/CornerCaseV0_1_0Test.t.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/test/regression/CornerCaseV0_1_0Test.t.sol b/test/regression/CornerCaseV0_1_0Test.t.sol index 388118f..797accb 100644 --- a/test/regression/CornerCaseV0_1_0Test.t.sol +++ b/test/regression/CornerCaseV0_1_0Test.t.sol @@ -29,6 +29,5 @@ contract CornerCaseV0_1_0Test is BaseFixture { // @note if it not identical a blockage will be suffer and force to wait for tx expiration assertEq(nonceDepositTx, nonceShutdownTx); assertEq(payloadDepositTx, payloadShutdownTx); - } }