Skip to content

Commit

Permalink
Merge branch 'main' into issue/52
Browse files Browse the repository at this point in the history
  • Loading branch information
gosuto-inzasheru authored Jun 10, 2024
2 parents 047cd4a + cf8b273 commit 3e9b560
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
19 changes: 18 additions & 1 deletion src/RoboSaverVirtualModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,11 @@ contract RoboSaverVirtualModule {
/// @return adjustPoolNeeded True if there is a deficit or surplus; false otherwise
/// @return execPayload The payload of the needed transaction
function checker() external view returns (bool adjustPoolNeeded, bytes memory execPayload) {
if (_isExternalTxQueued()) return (false, bytes("External transaction in queue, wait for it to be executed"));
/// @dev check if there is a transaction queued up in the delay module by an external entity
/// and it is not yet expired
if (_isExternalTxQueued() && !_isCleanQueueRequired()) {
return (false, bytes("External transaction in queue, wait for it to be executed"));
}

/// @dev check if there is a transaction queued up in the delay module by the virtual module itself
if (queuedTx.nonce != 0) {
Expand Down Expand Up @@ -271,6 +275,7 @@ contract RoboSaverVirtualModule {
/// @param _action The action to take: deposit or withdraw
/// @param _amount The amount of $EURe to deposit or withdraw
function adjustPool(PoolAction _action, uint256 _amount) external onlyKeeper {
if (_isCleanQueueRequired()) delayModule.skipExpired();
if (_isExternalTxQueued()) revert ExternalTxIsQueued();

if (_action == PoolAction.WITHDRAW) {
Expand Down Expand Up @@ -416,4 +421,16 @@ contract RoboSaverVirtualModule {
/// @dev Requires deducting 1 from the storage nonce, since the delay module increments after writing timestamp in their internal storage
if (block.timestamp - delayModule.getTxCreatedAt(_nonce - 1) <= delayModule.txCooldown()) isInCoolDown_ = true;
}

/// @notice Check if any transactions are expired
/// @return anyExpiredTxs_ True if any transactions are expired; false otherwise
function _isCleanQueueRequired() internal view returns (bool anyExpiredTxs_) {
/// @dev Pick latest `txNonce` as reference to check if it is expired, then trigger clean-up
if (
block.timestamp - delayModule.getTxCreatedAt(delayModule.txNonce())
> delayModule.txCooldown() + delayModule.txExpiration()
) {
anyExpiredTxs_ = true;
}
}
}
28 changes: 28 additions & 0 deletions test/AdjustPoolTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,32 @@ contract AdjustPoolTest is BaseFixture {
vm.expectRevert(abi.encodeWithSelector(RoboSaverVirtualModule.ExternalTxIsQueued.selector));
roboModule.adjustPool(RoboSaverVirtualModule.PoolAction.WITHDRAW, 5e18);
}

function test_When_QueueHasExpiredTxs() public {
// 1. queue dummy transfer - external tx
_transferOutBelowThreshold();
uint256 txNonceBeforeCleanup = delayModule.txNonce(); // in this case should be `0`
assertEq(txNonceBeforeCleanup, 0);

(bool canExec, bytes memory execPayload) = roboModule.checker();

assertFalse(canExec);
assertEq(execPayload, bytes("External transaction in queue, wait for it to be executed"));

// 2. force queue to expire
skip(COOLDOWN_PERIOD + EXPIRATION_PERIOD + 1);

// @note that here it is returning `false` but not anymore external tx being queued as blocker
// since it is already on expired status
(canExec, execPayload) = roboModule.checker();
assertFalse(canExec);
assertEq(execPayload, bytes("Neither deficit nor surplus; no action needed"));

// 3. trigger a normal flow (includes cleanup + queuing of a deposit)
vm.prank(KEEPER);
roboModule.adjustPool(RoboSaverVirtualModule.PoolAction.DEPOSIT, 2e18);

// asserts the clean up its checked, since it triggered `txNonce++`
assertGt(delayModule.txNonce(), txNonceBeforeCleanup);
}
}

0 comments on commit 3e9b560

Please sign in to comment.