This could lead to accounting issues, where a user's points are not updated for withdrawal but instead, the trading token is updated. This could lead to users receiving not receiving their points when they close a bid and withdraw. Their points will be stuck in the CapitalPool
contract.
pragma solidity ^0.8.13;
import {Test} from "forge-std/Test.sol";
import "forge-std/console.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.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 {MarketPlaceStatus} from "src/interfaces/ISystemConfig.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 {UpgradeableProxy} from "../src/proxy/UpgradeableProxy.sol";
contract TadleTest is Test {
TadleFactory tadleFactory;
SystemConfig systemConfig;
PreMarktes preMarktes;
DeliveryPlace deliveryPlace;
CapitalPool capitalPool;
TokenManager tokenManager;
address marketPlace;
MockERC20Token mockPointToken;
uint256 basePlatformFeeRate = 5_000;
uint256 baseReferralRate = 300_000;
bytes4 private constant INITIALIZE_OWNERSHIP_SELECTOR =
bytes4(keccak256(bytes("initializeOwnership(address)")));
address public deployer = makeAddr("deployer");
address public tadleAdmin = makeAddr("tadleAdmin");
address public backpackAdmin = makeAddr("backpackAdmin");
address[] users;
address payable user1;
address payable user2;
address payable user3;
address payable user4;
address payable user5;
address payable userX;
address payable public WETH = payable(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
address USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
address DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address binanceWhale = 0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503;
function setUp() public {
vm.createSelectFork("https://rpc.ankr.com/eth");
_createAndDealUsersTokens();
vm.startPrank(deployer);
tadleFactory = new TadleFactory(address(tadleAdmin));
SystemConfig systemConfigLogic = new SystemConfig();
PreMarktes preMarktesLogic = new PreMarktes();
DeliveryPlace deliveryPlaceLogic = new DeliveryPlace();
CapitalPool capitalPoolLogic = new CapitalPool();
TokenManager tokenManagerLogic = new TokenManager();
vm.stopPrank();
vm.startPrank(address(tadleAdmin));
bytes memory deploy_data = abi.encodeWithSelector(
INITIALIZE_OWNERSHIP_SELECTOR,
tadleAdmin
);
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)
);
vm.stopPrank();
vm.startPrank(address(deployer));
systemConfig = SystemConfig(systemConfigProxy);
preMarktes = PreMarktes(preMarktesProxy);
deliveryPlace = DeliveryPlace(deliveryPlaceProxy);
capitalPool = CapitalPool(capitalPoolProxy);
tokenManager = TokenManager(tokenManagerProxy);
vm.stopPrank();
vm.startPrank(address(backpackAdmin));
mockPointToken = new MockERC20Token("Backpack Points", "BPP");
deal(address(mockPointToken), tadleAdmin, 100_000_000e18);
deal(address(mockPointToken), user1, 100_000_000e18);
deal(address(mockPointToken), user2, 50_000_000e18);
vm.stopPrank();
vm.startPrank(tadleAdmin);
systemConfig.initialize(basePlatformFeeRate, baseReferralRate);
tokenManager.initialize(address(WETH));
address[] memory tokenAddressList = new address[](4);
tokenAddressList[0] = address(WETH);
tokenAddressList[1] = address(DAI);
tokenAddressList[2] = address(USDC);
tokenAddressList[2] = address(USDT);
tokenManager.updateTokenWhiteListed(tokenAddressList, true);
systemConfig.createMarketPlace("Backpack", false);
systemConfig.updateMarket(
"Backpack",
address(mockPointToken),
0.01 * 1e18,
1724112000,
1 days
);
marketPlace = GenerateAddress.generateMarketPlaceAddress("Backpack");
vm.stopPrank();
vm.label(address(tadleFactory), "TadleFactory");
vm.label(address(systemConfig), "SystemConfig");
vm.label(address(preMarktes), "PreMarktes");
vm.label(address(deliveryPlace), "DeliveryPlace");
vm.label(address(capitalPool), "CapitalPool");
vm.label(address(tokenManager), "TokenManager");
vm.label(address(marketPlace), "Backpack MarketPlace");
vm.label(address(mockPointToken), "Backpack Points");
vm.label(address(DAI), "DAI");
}
function _createAndDealUsersTokens() internal {
user1 = payable(makeAddr("user1"));
user2 = payable(makeAddr("user2"));
user3 = payable(makeAddr("user3"));
user4 = payable(makeAddr("user4"));
user5 = payable(makeAddr("user5"));
userX = payable(makeAddr("userX"));
users.push(user1);
users.push(user2);
users.push(user3);
users.push(user4);
users.push(user5);
for (uint256 i = 0; i < users.length; i++) {
vm.deal(users[i], 20 ether);
vm.prank(address(binanceWhale));
IERC20(USDC).transfer(users[i], 100_000e6);
deal(USDT, users[i], 100_000e6);
deal(DAI, users[i], 100_000e18);
deal(WETH, users[i], 20e18);
}
vm.deal(userX, 20 ether);
vm.prank(address(binanceWhale));
IERC20(USDC).transfer(userX, 100_000e6);
deal(USDT, userX, 100_000e6);
deal(DAI, userX, 100_000e18);
deal(WETH, userX, 20e18);
}
function testTadle() public {
createOffer();
}
function createOffer() public {
struct CreateOfferParams {
address marketPlace;
address tokenAddress;
uint256 points;
uint256 amount;
uint256 collateralRate;
uint256 eachTradeTax;
OfferType offerType;
OfferSettleType offerSettleType;
}
*/
vm.startPrank(address(user1));
IERC20(DAI).approve(address(tokenManager), type(uint256).max);
CreateOfferParams memory createOfferParams = CreateOfferParams(
marketPlace,
address(DAI),
1_000,
0.01 * 1e18,
12000,
300,
OfferType.Ask,
OfferSettleType.Turbo
);
preMarktes.createOffer(createOfferParams);
_offer: 0xE619a2899a8db14983538159ccE0d238074a235d,
_maker: 0x6a6E1BCA653147228386D44b6B93bE715c9f4497,
_stock: 0x41e7A7cD0C389cD6015D23df7A112c6CC19A192F,
*/
vm.stopPrank();
vm.startPrank(address(user3));
IERC20(DAI).approve(address(tokenManager), 20_000e18);
address offerAddr = GenerateAddress.generateOfferAddress(0);
preMarktes.createTaker(offerAddr, 1_000);
address stock1Addr = GenerateAddress.generateStockAddress(1);
IERC20(DAI).balanceOf(user3);
IERC20(mockPointToken).balanceOf(user3);
vm.stopPrank();
warp(1724112000 [1.724e9])
warp(1724198460 [1.724e9])
*/
uint256 currentTime = block.timestamp;
uint256 timeToSkip = 1724112000 - currentTime;
skip(timeToSkip);
skip(1 days);
vm.startPrank(address(user1));
IERC20(mockPointToken).approve(address(tokenManager), type(uint256).max);
deliveryPlace.settleAskMaker(offerAddr, 1_000);
vm.stopPrank();
vm.startPrank(address(user3));
deliveryPlace.closeBidTaker(stock1Addr);
IERC20(mockPointToken).balanceOf(user3);
IERC20(mockPointToken).balanceOf(address(capitalPool));
tokenManager.withdraw(address(mockPointToken), TokenBalanceType.PointToken);
vm.stopPrank();
IERC20(mockPointToken).balanceOf(user3);
IERC20(mockPointToken).balanceOf(address(capitalPool));
}
}