121 lines
No EOL
4.6 KiB
Solidity
121 lines
No EOL
4.6 KiB
Solidity
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
pragma solidity ^0.8.19;
|
|
|
|
/**
|
|
* @title Simple Scenario Analysis for LiquidityManager
|
|
* @notice Lightweight analysis script for researching profitable trading scenarios
|
|
* @dev Separated from unit tests to focus on research and scenario discovery
|
|
* Run with: forge script analysis/SimpleAnalysis.s.sol --ffi
|
|
*/
|
|
|
|
import "../test/LiquidityManager.t.sol";
|
|
|
|
contract SimpleAnalysis is LiquidityManagerTest {
|
|
|
|
uint256 public scenariosAnalyzed;
|
|
uint256 public profitableScenarios;
|
|
|
|
/// @notice Entry point for forge script execution
|
|
function run() public {
|
|
console.log("Starting LiquidityManager Scenario Analysis...");
|
|
console.log("This will analyze trading scenarios for profitability.");
|
|
|
|
// Example analysis with predefined parameters
|
|
uint8[] memory amounts = new uint8[](10);
|
|
amounts[0] = 100; amounts[1] = 50; amounts[2] = 75;
|
|
amounts[3] = 120; amounts[4] = 30; amounts[5] = 90;
|
|
amounts[6] = 45; amounts[7] = 110; amounts[8] = 60; amounts[9] = 80;
|
|
|
|
runAnalysis(10, 3, amounts);
|
|
|
|
console.log("Analysis complete. Check statistics:");
|
|
(uint256 total, uint256 profitable) = getStats();
|
|
console.log("Total scenarios:", total);
|
|
console.log("Profitable scenarios:", profitable);
|
|
}
|
|
|
|
/// @notice Analyzes a trading scenario for profitability
|
|
/// @dev Records CSV data if profitable - THIS IS NOT A UNIT TEST
|
|
function runAnalysis(uint8 numActions, uint8 frequency, uint8[] memory amounts) public {
|
|
// Bound inputs
|
|
vm.assume(numActions > 3 && numActions <= 50);
|
|
vm.assume(frequency > 0 && frequency < 20);
|
|
vm.assume(amounts.length >= numActions);
|
|
|
|
// Setup
|
|
_setupCustom(false, 50 ether);
|
|
|
|
uint256 balanceBefore = weth.balanceOf(account);
|
|
|
|
// Execute trading sequence (need to convert memory to calldata)
|
|
_executeRandomTradingSequenceWrapper(numActions, frequency, amounts);
|
|
|
|
uint256 balanceAfter = weth.balanceOf(account);
|
|
|
|
scenariosAnalyzed++;
|
|
|
|
// Check profitability
|
|
if (balanceAfter > balanceBefore) {
|
|
profitableScenarios++;
|
|
uint256 profit = balanceAfter - balanceBefore;
|
|
|
|
console.log("[ALERT] Profitable scenario found!");
|
|
console.log("Profit:", vm.toString(profit));
|
|
console.log("Actions:", numActions);
|
|
console.log("Frequency:", frequency);
|
|
|
|
// Write CSV for analysis to analysis folder
|
|
writeCSVToFile("./analysis/profitable_scenario.csv");
|
|
}
|
|
|
|
console.log("Scenario", scenariosAnalyzed, balanceAfter > balanceBefore ? "PROFIT" : "SAFE");
|
|
}
|
|
|
|
/// @notice Wrapper to handle memory to calldata conversion
|
|
function _executeRandomTradingSequenceWrapper(uint8 numActions, uint8 frequency, uint8[] memory amounts) internal {
|
|
// Create a simple trading sequence without the complex calldata dependency
|
|
uint8 f = 0;
|
|
|
|
for (uint i = 0; i < numActions && i < amounts.length; i++) {
|
|
uint256 amount = (uint256(amounts[i]) * 1 ether) + 1 ether;
|
|
uint256 harbergBal = harberg.balanceOf(account);
|
|
|
|
// Execute trade based on current balances
|
|
if (harbergBal == 0) {
|
|
amount = amount % (weth.balanceOf(account) / 2);
|
|
amount = amount == 0 ? weth.balanceOf(account) / 10 : amount;
|
|
if (amount > 0) buy(amount);
|
|
} else if (weth.balanceOf(account) == 0) {
|
|
sell(amount % harbergBal);
|
|
} else {
|
|
if (amount % 2 == 0) {
|
|
amount = amount % (weth.balanceOf(account) / 2);
|
|
amount = amount == 0 ? weth.balanceOf(account) / 10 : amount;
|
|
if (amount > 0) buy(amount);
|
|
} else {
|
|
sell(amount % harbergBal);
|
|
}
|
|
}
|
|
|
|
// Periodic recentering
|
|
if (f >= frequency) {
|
|
recenter(false);
|
|
f = 0;
|
|
} else {
|
|
f++;
|
|
}
|
|
}
|
|
|
|
// Final cleanup
|
|
uint256 finalHarbBal = harberg.balanceOf(account);
|
|
if (finalHarbBal > 0) {
|
|
sell(finalHarbBal);
|
|
}
|
|
recenter(true);
|
|
}
|
|
|
|
/// @notice Get analysis statistics
|
|
function getStats() public view returns (uint256 total, uint256 profitable) {
|
|
return (scenariosAnalyzed, profitableScenarios);
|
|
}
|
|
} |