diff --git a/src/interfaces/ISuperformRouterPlusAsync.sol b/src/interfaces/ISuperformRouterPlusAsync.sol index fe9f7bc5e..dff181c4a 100644 --- a/src/interfaces/ISuperformRouterPlusAsync.sol +++ b/src/interfaces/ISuperformRouterPlusAsync.sol @@ -44,6 +44,9 @@ interface ISuperformRouterPlusAsync is IBaseSuperformRouterPlus { uint256 newOutputAmount, uint256 expectedOutputAmount, uint256 userSlippage ); + /// @notice thrown if the refund is already requested + error REFUND_ALREADY_REQUESTED(); + /// @notice thrown to avoid processing the same rebalance payload twice error REBALANCE_ALREADY_PROCESSED(); diff --git a/src/router-plus/SuperformRouterPlusAsync.sol b/src/router-plus/SuperformRouterPlusAsync.sol index 09968d473..1f062bac7 100644 --- a/src/router-plus/SuperformRouterPlusAsync.sol +++ b/src/router-plus/SuperformRouterPlusAsync.sol @@ -430,6 +430,8 @@ contract SuperformRouterPlusAsync is ISuperformRouterPlusAsync, BaseSuperformRou function requestRefund(uint256 routerPlusPayloadId_, uint256 requestedAmount) external { Refund memory r = refunds[routerPlusPayloadId_]; + if (r.amount != 0) revert REFUND_ALREADY_REQUESTED(); + if (msg.sender != r.receiver) revert INVALID_REQUESTER(); if (r.interimToken == address(0)) revert INVALID_REFUND_DATA(); diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 4c085e773..92a1ea8da 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -2494,6 +2494,10 @@ contract SuperformRouterPlusTest is ProtocolActions { (, address refundToken,) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); assertEq(refundToken, address(args.interimAsset)); + // @dev testing refund already requested + vm.expectRevert(ISuperformRouterPlusAsync.REFUND_ALREADY_REQUESTED.selector); + SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).requestRefund(1, 100); + // Step 6: Approve refund /// @dev testing invalid approver (not core state registry)