pragma solidity ^0.8.13;
import {Test, console2} from "forge-std/Test.sol";
import {SystemConfig} from "../src/core/SystemConfig.sol";
import {CapitalPool} from "../src/core/CapitalPool.sol";
import {TokenManager} from "../src/core/TokenManager.sol";
import {PreMarktes} from "../src/core/PreMarkets.sol";
import {DeliveryPlace} from "../src/core/DeliveryPlace.sol";
import {TadleFactory} from "../src/factory/TadleFactory.sol";
import {OfferStatus, StockStatus, AbortOfferStatus, OfferType, StockType, OfferSettleType} from "../src/storage/OfferStatus.sol";
import {IPerMarkets, OfferInfo, StockInfo, MakerInfo, CreateOfferParams} from "../src/interfaces/IPerMarkets.sol";
import {TokenBalanceType, ITokenManager} from "../src/interfaces/ITokenManager.sol";
import {GenerateAddress} from "../src/libraries/GenerateAddress.sol";
import {MockERC20Token} from "./mocks/MockERC20Token.sol";
import {WETH9} from "./mocks/WETH9.sol";
import {UpgradeableProxy} from "../src/proxy/UpgradeableProxy.sol";
contract Withdraw_Bug is Test {
SystemConfig systemConfig;
CapitalPool capitalPool;
TokenManager tokenManager;
PreMarktes preMarktes;
DeliveryPlace deliveryPlace;
address marketPlace;
WETH9 weth9;
MockERC20Token mockUSDCToken;
MockERC20Token mockPointToken;
address admin = vm.addr(0x123);
address user = vm.addr(0x124);
address user2 = vm.addr(0xd125);
uint256 basePlatformFeeRate = 5_000;
uint256 baseReferralRate = 300_000;
bytes4 private constant INITIALIZE_OWNERSHIP_SELECTOR =
bytes4(keccak256(bytes("initializeOwnership(address)")));
function setUp() public {
weth9 = new WETH9();
TadleFactory tadleFactory = new TadleFactory(admin);
mockUSDCToken = new MockERC20Token();
mockPointToken = new MockERC20Token();
SystemConfig systemConfigLogic = new SystemConfig();
CapitalPool capitalPoolLogic = new CapitalPool();
TokenManager tokenManagerLogic = new TokenManager();
PreMarktes preMarktesLogic = new PreMarktes();
DeliveryPlace deliveryPlaceLogic = new DeliveryPlace();
bytes memory deploy_data = abi.encodeWithSelector(
INITIALIZE_OWNERSHIP_SELECTOR,
admin
);
vm.startPrank(admin);
address systemConfigProxy = tadleFactory.deployUpgradeableProxy(
1,
address(systemConfigLogic),
bytes(deploy_data)
);
address preMarktesProxy = tadleFactory.deployUpgradeableProxy(
2,
address(preMarktesLogic),
bytes(deploy_data)
);
address deliveryPlaceProxy = tadleFactory.deployUpgradeableProxy(
3,
address(deliveryPlaceLogic),
bytes(deploy_data)
);
address capitalPoolProxy = tadleFactory.deployUpgradeableProxy(
4,
address(capitalPoolLogic),
bytes(deploy_data)
);
address tokenManagerProxy = tadleFactory.deployUpgradeableProxy(
5,
address(tokenManagerLogic),
bytes(deploy_data)
);
systemConfig = SystemConfig(systemConfigProxy);
capitalPool = CapitalPool(capitalPoolProxy);
tokenManager = TokenManager(tokenManagerProxy);
preMarktes = PreMarktes(preMarktesProxy);
deliveryPlace = DeliveryPlace(deliveryPlaceProxy);
systemConfig.initialize(basePlatformFeeRate, baseReferralRate);
tokenManager.initialize(address(weth9));
address[] memory tokenAddressList = new address[](2);
tokenAddressList[0] = address(mockUSDCToken);
tokenAddressList[1] = address(weth9);
tokenManager.updateTokenWhiteListed(tokenAddressList, true);
systemConfig.createMarketPlace("Backpack", false);
marketPlace = GenerateAddress.generateMarketPlaceAddress("Backpack");
deal(address(mockUSDCToken), admin, 100000000 * 10 ** 18);
vm.stopPrank();
vm.warp(1719826275);
}
function test_unable_to_Withdraw () public {
deal(user, 1000);
deal(address(mockUSDCToken), user, 2000);
deal(address(weth9), address(capitalPool), 2000);
uint256 offerId = 0 ;
address makerAddr = GenerateAddress.generateMakerAddress(offerId);
address offerAddr = GenerateAddress.generateOfferAddress(offerId);
address stockAddr = GenerateAddress.generateStockAddress(offerId);
address stock1Addr = GenerateAddress.generateStockAddress(1);
address offer1Addr = GenerateAddress.generateOfferAddress(1);
uint256 _points = 500;
uint256 _amount = 63 ;
uint256 collateralRate = 12000;
uint256 tax = 500 ;
CreateOfferParams memory params = CreateOfferParams(
marketPlace,
address(mockUSDCToken),
_points,
_amount,
collateralRate,
tax,
OfferType.Ask,
OfferSettleType.Protected
);
vm.startPrank(user);
mockUSDCToken.approve(address(tokenManager), type(uint256).max);
uint256 startingUserBalance = mockUSDCToken.balanceOf(user);
vm.expectEmit(true, true, true, true , address(preMarktes));
emit CreateOffer(
offerAddr,
makerAddr,
stockAddr,
marketPlace,
user,
_points,
_amount
);
preMarktes.createOffer{value : 500}(params);
uint256 userBalanceAfterCreateOffer = mockUSDCToken.balanceOf(user);
assertEq(userBalanceAfterCreateOffer, startingUserBalance - 76);
uint256 poolbalance = mockUSDCToken.balanceOf(address(capitalPool));
assertEq(poolbalance , 76);
preMarktes.createTaker{value: 400}(offerAddr, 400);
uint256 poolbalance1 = mockUSDCToken.balanceOf(address(capitalPool));
assertEq(poolbalance1 , 129);
uint256 claimAbleAmount1 = tokenManager.userTokenBalanceMap(user, address(mockUSDCToken), TokenBalanceType.SalesRevenue);
assertEq(claimAbleAmount1 , 51);
bytes4 selector = ApproveFailed.selector;
vm.expectRevert(abi.encodeWithSelector(selector));
tokenManager.withdraw(address(mockUSDCToken), TokenBalanceType.SalesRevenue);
preMarktes.createTaker(offerAddr, 100);
uint256 poolbalance2 = mockUSDCToken.balanceOf(address(capitalPool));
assertEq(poolbalance2 , 142);
preMarktes.listOffer(stock1Addr, _amount, collateralRate);
uint256 poolbalance3 = mockUSDCToken.balanceOf(address(capitalPool));
assertEq(poolbalance3 , 218);
preMarktes.closeOffer(stock1Addr, offer1Addr);
uint256 poolbalance4 = mockUSDCToken.balanceOf(address(capitalPool));
assertTrue(poolbalance4 == poolbalance3);
preMarktes.relistOffer(stock1Addr, offer1Addr);
uint256 poolbalance5 = mockUSDCToken.balanceOf(address(capitalPool));
assertTrue(poolbalance5 > poolbalance4);
preMarktes.abortAskOffer(stock1Addr, offer1Addr);
uint256 claimAbleAmount2 = tokenManager.userTokenBalanceMap(user, address(mockUSDCToken), TokenBalanceType.MakerRefund);
assertTrue(claimAbleAmount2 == 150);
bytes4 selector0 = ApproveFailed.selector;
vm.expectRevert(abi.encodeWithSelector(selector0));
tokenManager.withdraw(address(mockUSDCToken), TokenBalanceType.MakerRefund);
vm.stopPrank();
}
error ApproveFailed();
event CreateOffer(
address indexed _offer,
address indexed _maker,
address indexed _stock,
address _marketPlace,
address _authority,
uint256 _points,
uint256 _amount
);
}