Unsold tokens from a FPAM auction, will be stuck in the protocol, after the auction concludes
The `Axis-Finance` protocol allows sellers to create two types of auctions: FPAM & EMPAM. An FPAM auction allows sellers to set a price, and a maxPayout, as well as create a prefunded auction. The seller of a FPAM auction can cancel it while it is still active by calling the cancel function which in turn calls the cancelAuction() function. If the auction is prefunded, and canceled while still active, all remaining funds will be transferred back to the seller. The problem arises if an FPAM prefunded auction is created, not all of the prefunded supply is bought by users, and the auction concludes. There is no way for the `baseTokens` still in the contract, to be withdrawn from the protocol, and they will be forever stuck in the `Axis-Finance` protocol. As can be seen from the below code snippet cancelAuction() function checks if an auction is concluded, and if it is the function reverts.\\n```\\n    function _revertIfLotConcluded(uint96 lotId_) internal view virtual {\\n        // Beyond the conclusion time\\n        if (lotData[lotId_].conclusion < uint48(block.timestamp)) {\\n            revert Auction_MarketNotActive(lotId_);\\n        }\\n\\n        // Capacity is sold-out, or cancelled\\n        if (lotData[lotId_].capacity == 0) revert Auction_MarketNotActive(lotId_);\\n    }\\n```\\n\\nGist After following the steps in the above mentioned gist add the following test to the `AuditorTests.t.sol` file\\n```\\nfunction test_FundedPriceAuctionStuckFunds() public {\\n        vm.startPrank(alice);\\n        Veecode veecode = fixedPriceAuctionModule.VEECODE();\\n        Keycode keycode = keycodeFromVeecode(veecode);\\n        bytes memory _derivativeParams = "";\\n        uint96 lotCapacity = 75_000_000_000e18; // this is 75 billion tokens\\n        mockBaseToken.mint(alice, lotCapacity);\\n        mockBaseToken.approve(address(auctionHouse), type(uint256).max);\\n\\n        FixedPriceAuctionModule.FixedPriceParams  memory myStruct = FixedPriceAuctionModule.FixedPriceParams({\\n            price: uint96(1e18), \\n            maxPayoutPercent: uint24(1e5)\\n        });\\n\\n        Auctioneer.RoutingParams memory routingA = Auctioneer.RoutingParams({\\n            auctionType: keycode,\\n            baseToken: mockBaseToken,\\n            quoteToken: mockQuoteToken,\\n            curator: curator,\\n            callbacks: ICallback(address(0)),\\n            callbackData: abi.encode(""),\\n            derivativeType: toKeycode(""),\\n            derivativeParams: _derivativeParams,\\n            wrapDerivative: false,\\n            prefunded: true\\n        });\\n\\n        Auction.AuctionParams memory paramsA = Auction.AuctionParams({\\n            start: 0,\\n            duration: 1 days,\\n            capacityInQuote: false,\\n            capacity: lotCapacity,\\n            implParams: abi.encode(myStruct)\\n        });\\n\\n        string memory infoHashA;\\n        auctionHouse.auction(routingA, paramsA, infoHashA);       \\n        vm.stopPrank();\\n\\n        vm.startPrank(bob);\\n        uint96 fundingBeforePurchase;\\n        uint96 fundingAfterPurchase;\\n        (,fundingBeforePurchase,,,,,,,) = auctionHouse.lotRouting(0);\\n        console2.log("Here is the funding normalized before purchase: ", fundingBeforePurchase/1e18);\\n        mockQuoteToken.mint(bob, 10_000_000_000e18);\\n        mockQuoteToken.approve(address(auctionHouse), type(uint256).max);\\n        Router.PurchaseParams memory purchaseParams = Router.PurchaseParams({\\n            recipient: bob,\\n            referrer: address(0),\\n            lotId: 0,\\n            amount: 10_000_000_000e18,\\n            minAmountOut: 10_000_000_000e18,\\n            auctionData: abi.encode(0),\\n            permit2Data: ""\\n        });\\n        bytes memory callbackData = "";\\n        auctionHouse.purchase(purchaseParams, callbackData);\\n        (,fundingAfterPurchase,,,,,,,) = auctionHouse.lotRouting(0);\\n        console2.log("Here is the funding normalized after purchase: ", fundingAfterPurchase/1e18);\\n        console2.log("Balance of seler of quote tokens: ", mockQuoteToken.balanceOf(alice)/1e18);\\n        console2.log("Balance of bob in base token: ", mockBaseToken.balanceOf(bob)/1e18);\\n        console2.log("Balance of auction house in base token: ", mockBaseToken.balanceOf(address(auctionHouse)) /1e18);\\n        skip(86401);\\n        vm.stopPrank();\\n\\n        vm.startPrank(alice);\\n        vm.expectRevert(\\n            abi.encodeWithSelector(Auction.Auction_MarketNotActive.selector, 0)\\n        );\\n        auctionHouse.cancel(uint96(0), callbackData);\\n        vm.stopPrank();\\n    }\\n```\\n\\n```\\nLogs:\\n  Here is the funding normalized before purchase:  75000000000\\n  Here is the funding normalized after purchase:  65000000000\\n  Balance of seler of quote tokens:  10000000000\\n  Balance of bob in base token:  10000000000\\n  Balance of auction house in base token:  65000000000\\n```\\n\\nTo run the test use: `forge test -vvv --mt test_FundedPriceAuctionStuckFunds`
Implement a function, that allows sellers to withdraw the amount left for a prefunded FPAM auction they have created, once the auction has concluded.
If a prefunded FPAM auction concludes and there are still tokens, not bought from the users, they will be stuck in the `Axis-Finance` protocol.
```\\n    function _revertIfLotConcluded(uint96 lotId_) internal view virtual {\\n        // Beyond the conclusion time\\n        if (lotData[lotId_].conclusion < uint48(block.timestamp)) {\\n            revert Auction_MarketNotActive(lotId_);\\n        }\\n\\n        // Capacity is sold-out, or cancelled\\n        if (lotData[lotId_].capacity == 0) revert Auction_MarketNotActive(lotId_);\\n    }\\n```\\n