diff --git a/.gitmodules b/.gitmodules index 7539389..b938458 100644 --- a/.gitmodules +++ b/.gitmodules @@ -54,3 +54,6 @@ [submodule "lib/pt-v5-prize-pool-fee-burner"] path = lib/pt-v5-prize-pool-fee-burner url = https://github.com/GenerationSoftware/pt-v5-prize-pool-fee-burner +[submodule "lib/fixed-liquidator"] + path = lib/fixed-liquidator + url = https://github.com/generationsoftware/fixed-liquidator diff --git a/config/optimism.json b/config/optimism.json index c3f8efb..7074c96 100644 --- a/config/optimism.json +++ b/config/optimism.json @@ -1,32 +1,17 @@ { "simulation": { - "num_users": "128", + "num_users": "2", "time_step": "1800", - "tvl_usd": "10000000", + "tvl_usd": "5000000", "verbosity": "1", + "duration_draws": "6", + + "eth_price_usd_per_draw" : [ + "30" + ], - "duration_draws": "5", "apr_for_each_draw" : [ - "25000000000000000", - "30000000000000000", - "35000000000000000", - "40000000000000000", - "45000000000000000", - "50000000000000000", - "55000000000000000", - "60000000000000000", - "65000000000000000", - "70000000000000000", - "60000000000000000", - "50000000000000000", - "30000000000000000", - "20000000000000000", - "10000000000000000", - "10000000000000000", - "10000000000000000", - "10000000000000000", - "10000000000000000", - "10000000000000000" + "30000000000000000" ] }, @@ -35,9 +20,9 @@ "draw_timeout": "30", "grand_prize_period_draws": "365", "number_of_tiers": "4", - "tier_shares": "100", + "tier_shares": "200", "canary_shares": "5", - "reserve_shares": "20", + "reserve_shares": "40", "tier_liquidity_utilization_rate": "500000000000000000" }, @@ -53,14 +38,14 @@ }, "claimer": { - "claimer_min_fee": "100000000000", - "claimer_max_fee": "1000000000000000000" + "claimer_min_fee": "100", + "claimer_max_fee": "10000000" }, "gas": { - "start_draw_cost_in_eth": "40000000000000", - "award_draw_cost_in_eth": "100000000000000", - "claim_cost_in_eth": "60000000000000", - "liquidation_cost_in_eth": "100000000000000" + "start_draw_cost_in_usd": "10", + "award_draw_cost_in_usd": "10", + "claim_cost_in_usd": "10", + "liquidation_cost_in_usd": "10" } } diff --git a/lib/fixed-liquidator b/lib/fixed-liquidator new file mode 160000 index 0000000..3bac408 --- /dev/null +++ b/lib/fixed-liquidator @@ -0,0 +1 @@ +Subproject commit 3bac4089d10e9465c87dbee6a036b6cb7440b48f diff --git a/remappings.txt b/remappings.txt index f14fd2a..762aad3 100644 --- a/remappings.txt +++ b/remappings.txt @@ -22,3 +22,4 @@ pt-v5-prize-pool/=lib/pt-v5-prize-pool/src/ pt-v5-twab-controller/=lib/pt-v5-twab-controller/src/ pt-v5-vault/=lib/pt-v5-vault/src/ pt-v5-vault-test/=lib/pt-v5-vault/test/ +fixed-liquidator/=lib/fixed-liquidator/src/ \ No newline at end of file diff --git a/scripts/ethereum.sh b/scripts/ethereum.sh index 242e553..045d093 100755 --- a/scripts/ethereum.sh +++ b/scripts/ethereum.sh @@ -1,3 +1,3 @@ -#! /usr/local/bin/bash +#!/usr/bin/env bash rm config/output/ethereum-output.csv CONFIG=config/ethereum.json OUTPUT=config/output/ethereum-output.csv forge test -vvv --mt testSingleChain diff --git a/scripts/optimism.sh b/scripts/optimism.sh index e6762a0..9df9e5a 100755 --- a/scripts/optimism.sh +++ b/scripts/optimism.sh @@ -1,3 +1,3 @@ -#! /usr/local/bin/bash +#!/usr/bin/env bash rm config/output/optimism-output.csv CONFIG=config/optimism.json OUTPUT=config/output/optimism-output.csv forge test -vvv --mt testSingleChain diff --git a/src/agent/ClaimerAgent.sol b/src/agent/ClaimerAgent.sol index d69d3b6..81108ec 100644 --- a/src/agent/ClaimerAgent.sol +++ b/src/agent/ClaimerAgent.sol @@ -92,7 +92,7 @@ contract ClaimerAgent is Utils { // see if any are worth claiming { uint claimFees = claimer.computeTotalFees(tier, tierPrizes); - uint cost = tierPrizes * env.config().gas().claimCostInEth; + uint cost = env.config().usdToWeth(tierPrizes * env.config().gas().claimCostInUsd); if (isLogging(3)) { console2.log( "\tclaimFees for drawId %s tier %s with prize size %e:", @@ -312,7 +312,7 @@ contract ClaimerAgent is Utils { if (isLogging(2)) { console2.log( "+++++++++++++++++++++ Prize Claim Cost:", - env.config().gas().claimCostInEth + env.config().gas().claimCostInUsd ); console2.log( "+++++++++++++++++++++ Draw", diff --git a/src/agent/DrawAgent.sol b/src/agent/DrawAgent.sol index c7a624b..69e511d 100644 --- a/src/agent/DrawAgent.sol +++ b/src/agent/DrawAgent.sol @@ -44,7 +44,7 @@ contract DrawAgent is StdCheats, Utils { } function willFinishDraw() public view returns (bool) { - uint256 finishDrawCost = env.config().gas().finishDrawCostInEth; + uint256 finishDrawCost = env.config().usdToWeth(env.config().gas().finishDrawCostInUsd); uint256 minimumFinishDrawProfit = getMinimumProfit(finishDrawCost); uint256 finishDrawProfit; @@ -69,9 +69,7 @@ contract DrawAgent is StdCheats, Utils { if (drawManager.canStartDraw()) { uint fee = drawManager.startDrawReward(); - // console2.log("fee %e", fee); - uint256 startDrawCost = env.config().gas().startDrawCostInEth; - // console2.log("cost %e", startDrawCost); + uint256 startDrawCost = env.config().usdToWeth(env.config().gas().startDrawCostInUsd); uint256 startDrawProfit = fee < startDrawCost ? 0 : fee - startDrawCost; if (startDrawProfit >= getMinimumProfit(startDrawCost)) { // console2.log("started draw", drawId); diff --git a/src/agent/LiquidatorAgent.sol b/src/agent/LiquidatorAgent.sol index ae25157..ac3d503 100644 --- a/src/agent/LiquidatorAgent.sol +++ b/src/agent/LiquidatorAgent.sol @@ -7,8 +7,8 @@ import { SD59x18, wrap, convert, uMAX_SD59x18 } from "prb-math/SD59x18.sol"; import { ERC20PermitMock } from "pt-v5-vault-test/contracts/mock/ERC20PermitMock.sol"; import { ILiquidationPair } from "pt-v5-liquidator-interfaces/ILiquidationPair.sol"; -import { LiquidationPair } from "pt-v5-cgda-liquidator/LiquidationPair.sol"; -import { LiquidationRouter } from "pt-v5-cgda-liquidator/LiquidationRouter.sol"; +import { FixedLiquidationPair } from "fixed-liquidator/FixedLiquidationPair.sol"; +import { FixedLiquidationRouter } from "fixed-liquidator/FixedLiquidationRouter.sol"; import { PrizePool } from "pt-v5-prize-pool/PrizePool.sol"; import { SingleChainEnvironment } from "../environment/SingleChainEnvironment.sol"; @@ -25,13 +25,17 @@ contract LiquidatorAgent is Utils { PrizePool public prizePool; ERC20PermitMock public prizeToken; - LiquidationRouter public router; + FixedLiquidationRouter public router; string liquidatorCsv; uint public burnedPool; mapping(uint24 drawId => uint256 totalBurnedPool) public totalBurnedPoolPerDraw; + mapping(uint24 drawId => uint256 amountIn) public totalAmountInPerDraw; + mapping(uint24 drawId => uint256 amountOut) public totalAmountOutPerDraw; + mapping(uint24 drawId => uint256 amountIn) public feeBurnerAmountInPerDraw; + mapping(uint24 drawId => uint256 amountOut) public feeBurnerAmountOutPerDraw; constructor(SingleChainEnvironment _env) { env = _env; @@ -51,11 +55,13 @@ contract LiquidatorAgent is Utils { uint24 openDrawId = prizePool.getOpenDrawId(); (amountOut, amountIn, profit) = checkLiquidationPair(wethUsdValue, poolUsdValue, wethUsdValue, env.pair()); if (profit.gt(wrap(0))) { - // console2.log("draw %s: liquidating %s for %s ", openDrawId, amountOut, amountIn); + totalAmountInPerDraw[openDrawId] += amountIn; + totalAmountOutPerDraw[openDrawId] += amountOut; } (amountOut, amountIn, profit) = checkLiquidationPair(poolUsdValue, wethUsdValue, wethUsdValue, env.feeBurnerPair()); if (profit.gt(wrap(0))) { - totalBurnedPoolPerDraw[openDrawId] += amountIn; + feeBurnerAmountInPerDraw[openDrawId] += amountIn; + feeBurnerAmountOutPerDraw[openDrawId] += amountOut; } } @@ -65,7 +71,6 @@ contract LiquidatorAgent is Utils { (amountOut, amountIn, profit) = _findBestProfit(tokenInValueUsd, tokenOutValueUsd, ethValueUsd, pair); // if (isFeeBurner(pair) && maxAmountOut > 0) { - // console2.log("Available to burn: %e", maxAmountOut); // } // console2.log("checkLiquidationPair amountOut %e", amountOut); // console2.log("checkLiquidationPair amountIn %e", amountIn); @@ -75,19 +80,21 @@ contract LiquidatorAgent is Utils { tokenIn.mint(address(this), amountIn); tokenIn.approve(address(router), amountIn); router.swapExactAmountOut( - LiquidationPair(address(pair)), + FixedLiquidationPair(address(pair)), address(this), amountOut, uint256(uMAX_SD59x18 / 1e18), // NOTE: uMAX_SD59x18/1e18 for DaLiquidator block.timestamp + 10 ); - if (isFeeBurner(pair)) { burnedPool += amountIn; } - uint256 elapsedSinceDrawEnded = block.timestamp - - prizePool.drawClosesAt(prizePool.getLastAwardedDrawId()); + + uint256 elapsedSinceDrawEnded; + // uint256 elapsedSinceDrawEnded = block.timestamp - + // prizePool.drawClosesAt(prizePool.getLastAwardedDrawId()); + // SD59x18 efficiency = convert(int256(amountIn)).div(convert(int256(amountOutInPrizeTokens))); // uint256 efficiencyPercent = uint256(convert(efficiency.mul(convert(100)))); @@ -106,6 +113,7 @@ contract LiquidatorAgent is Utils { logs[10] = 0; logs[11] = pair.maxAmountOut(); + logUint256ToCsv(liquidatorCsvFile, logs); } } @@ -143,7 +151,11 @@ contract LiquidatorAgent is Utils { uint256 amountOut ) public view returns (SD59x18) { SD59x18 amountOutInUsd = tokenOutValueUsd.mul(convert(int256(amountOut))); - SD59x18 cost = tokenInValueUsd.mul(convert(int256(amountIn))).add(computeGasCostInUsd(ethValueUsd, env.config().gas().liquidationCostInEth)); + if (amountIn > 57896044618658097711785492504343953926634992332820282019728) { + return wrap(0); + } + SD59x18 capitalCost = tokenInValueUsd.mul(convert(int256(amountIn)));//.add(convert(int256(env.config().gas().liquidationCostInUsd))); + SD59x18 cost = capitalCost.add(convert(int256(env.config().gas().liquidationCostInUsd))); return cost.lt(amountOutInUsd) ? amountOutInUsd.sub(cost) : wrap(0); } diff --git a/src/environment/SingleChainEnvironment.sol b/src/environment/SingleChainEnvironment.sol index e0ff01f..6d85949 100644 --- a/src/environment/SingleChainEnvironment.sol +++ b/src/environment/SingleChainEnvironment.sol @@ -23,8 +23,10 @@ import { Claimer } from "pt-v5-claimer/Claimer.sol"; import { ILiquidationSource } from "pt-v5-liquidator-interfaces/ILiquidationSource.sol"; import { ILiquidationPair } from "pt-v5-liquidator-interfaces/ILiquidationPair.sol"; -import { LiquidationPairFactory } from "pt-v5-cgda-liquidator/LiquidationPairFactory.sol"; -import { LiquidationRouter } from "pt-v5-cgda-liquidator/LiquidationRouter.sol"; +// import { LiquidationPairFactory } from "pt-v5-cgda-liquidator/LiquidationPairFactory.sol"; +// import { LiquidationRouter } from "pt-v5-cgda-liquidator/LiquidationRouter.sol"; +import { FixedLiquidationPairFactory } from "fixed-liquidator/FixedLiquidationPairFactory.sol"; +import { FixedLiquidationRouter } from "fixed-liquidator/FixedLiquidationRouter.sol"; import { YieldVaultMintRate } from "../YieldVaultMintRate.sol"; @@ -55,7 +57,7 @@ contract SingleChainEnvironment is Utils, StdCheats { YieldVaultMintRate public yieldVault; ILiquidationPair public pair; Claimer public claimer; - LiquidationRouter public router; + FixedLiquidationRouter public router; FeeBurner public feeBurner; ILiquidationPair public feeBurnerPair; @@ -135,6 +137,7 @@ contract SingleChainEnvironment is Utils, StdCheats { claimerConfig.maxFeePortionOfPrize ); + console2.log("Claimer DecayConstant ", claimer.decayConstant().unwrap()); // console2.log("SingleChainEnvironment constructor 6"); underlyingToken.mint(address(this), vaultFactory.YIELD_BUFFER()); @@ -162,10 +165,10 @@ contract SingleChainEnvironment is Utils, StdCheats { SD59x18 wethUsdValue = config.wethUsdValueOverTime().get(block.timestamp); SD59x18 poolUsdValue = config.poolUsdValueOverTime().get(block.timestamp); - LiquidationPairFactory pairFactory = new LiquidationPairFactory(); - vm.label(address(pairFactory), "LiquidationPairFactory"); - LiquidationRouter cgdaRouter = new LiquidationRouter(pairFactory); - vm.label(address(cgdaRouter), "LiquidationRouter"); + FixedLiquidationPairFactory pairFactory = new FixedLiquidationPairFactory(); + vm.label(address(pairFactory), "FixedLiquidationPairFactory"); + FixedLiquidationRouter fixedRouter = new FixedLiquidationRouter(pairFactory); + vm.label(address(fixedRouter), "FixedLiquidationRouter"); // console2.log( // "initializeCgdaLiquidator _liquidatorConfig.exchangeRatePrizeTokenToUnderlying", // _liquidatorConfig.exchangeRatePrizeTokenToUnderlying.unwrap() @@ -187,19 +190,15 @@ contract SingleChainEnvironment is Utils, StdCheats { ILiquidationSource(address(vault)), address(prizeToken), address(vault), - config.prizePool().drawPeriodSeconds, - uint32(config.prizePool().firstDrawOpensAt), - config.getTargetFirstSaleTime(), - config.getDecayConstant(), - wethAmount, // weth is token in - poolAmount, // pool is token out - 1e18 // min is 1 pool being sold + config.prizePool().drawPeriodSeconds / 3, + 0.00001e18, + 0 // no smoothing ) ) ); vm.label(address(pair), "VaultLiquidationPair"); - router = LiquidationRouter(address(cgdaRouter)); + router = FixedLiquidationRouter(address(fixedRouter)); vault.setLiquidationPair(address(pair)); feeBurnerPair = ILiquidationPair( @@ -208,13 +207,9 @@ contract SingleChainEnvironment is Utils, StdCheats { ILiquidationSource(address(feeBurner)), address(poolToken), address(prizeToken), - config.prizePool().drawPeriodSeconds, - uint32(config.prizePool().firstDrawOpensAt), - config.getTargetFirstSaleTime(), - config.getDecayConstant(), - poolAmount, // pool is token in (burn) - wethAmount, // weth is token out - wethAmount // 1 pool worth of weth being sold + config.prizePool().drawPeriodSeconds / 3, + 1e18, // 1 POOL, + 0.95e18 // very high smoothing ) ) ); diff --git a/src/utils/Config.sol b/src/utils/Config.sol index 3dd43d1..48e2616 100644 --- a/src/utils/Config.sol +++ b/src/utils/Config.sol @@ -53,12 +53,14 @@ struct DrawManagerConfig { // Gas configs struct GasConfig { - uint256 startDrawCostInEth; - uint256 finishDrawCostInEth; - uint256 claimCostInEth; - uint256 liquidationCostInEth; + uint256 startDrawCostInUsd; + uint256 finishDrawCostInUsd; + uint256 claimCostInUsd; + uint256 liquidationCostInUsd; } +uint constant USD_DECIMALS = 3; + contract Config is CommonBase { using SafeCast for uint256; @@ -85,15 +87,12 @@ contract Config is CommonBase { function load(string memory filepath) public { string memory config = vm.readFile(filepath); - wethUsdValueOverTime = new SD59x18OverTime(); - wethUsdValueOverTime.add(block.timestamp, convert(3000e2).div(convert(1e18))); // USD / WETH - poolUsdValueOverTime = new SD59x18OverTime(); - poolUsdValueOverTime.add(block.timestamp, convert(1e2).div(convert(1e18))); // USD / POOL + poolUsdValueOverTime.add(block.timestamp, convert(int(10**USD_DECIMALS)).div(convert(1e18))); // USD / POOL _simulation.numUsers = vm.parseJsonUint(config, "$.simulation.num_users"); _simulation.timeStep = vm.parseJsonUint(config, "$.simulation.time_step"); - _simulation.totalValueLocked = uint(convert(convert(int(vm.parseJsonUint(config, "$.simulation.tvl_usd"))).mul(convert(1e2)).div(poolUsdValueOverTime.get(block.timestamp)))); + _simulation.totalValueLocked = uint(convert(convert(int(vm.parseJsonUint(config, "$.simulation.tvl_usd"))).mul(convert(int(10**USD_DECIMALS))).div(poolUsdValueOverTime.get(block.timestamp)))); _simulation.verbosity = vm.parseJsonUint(config, "$.simulation.verbosity"); _simulation.durationDraws = vm.parseJsonUint(config, "$.simulation.duration_draws"); @@ -107,8 +106,6 @@ contract Config is CommonBase { _prizePool.drawTimeout = vm.parseJsonUint(config, "$.prize_pool.draw_timeout").toUint24(); _prizePool.tierLiquidityUtilizationRate = vm.parseJsonUint(config, "$.prize_pool.tier_liquidity_utilization_rate"); - console2.log("???? Config.load _prizePool.tierLiquidityUtilizationRate: ", _prizePool.tierLiquidityUtilizationRate); - _drawManager.auctionDuration = vm.parseJsonUint(config, "$.draw_manager.auction_duration").toUint64(); _drawManager.auctionTargetTime = vm.parseJsonUint(config, "$.draw_manager.auction_target_time").toUint64(); _drawManager.auctionMaxReward = vm.parseJsonUint(config, "$.draw_manager.auction_max_reward"); @@ -121,10 +118,21 @@ contract Config is CommonBase { _claimer.timeToReachMaxFee = getClaimerTimeToReachMaxFee(); _claimer.maxFeePortionOfPrize = getClaimerMaxFeePortionOfPrize(); - _gas.startDrawCostInEth = vm.parseJsonUint(config, "$.gas.start_draw_cost_in_eth"); - _gas.finishDrawCostInEth = vm.parseJsonUint(config, "$.gas.award_draw_cost_in_eth"); - _gas.claimCostInEth = vm.parseJsonUint(config, "$.gas.claim_cost_in_eth"); - _gas.liquidationCostInEth = vm.parseJsonUint(config, "$.gas.liquidation_cost_in_eth"); + _gas.startDrawCostInUsd = vm.parseJsonUint(config, "$.gas.start_draw_cost_in_usd"); + _gas.finishDrawCostInUsd = vm.parseJsonUint(config, "$.gas.award_draw_cost_in_usd"); + _gas.claimCostInUsd = vm.parseJsonUint(config, "$.gas.claim_cost_in_usd"); + _gas.liquidationCostInUsd = vm.parseJsonUint(config, "$.gas.liquidation_cost_in_usd"); + + wethUsdValueOverTime = new SD59x18OverTime(); + uint[] memory ethPrices = vm.parseJsonUintArray(config, "$.simulation.eth_price_usd_per_draw"); + if (ethPrices.length > 0) { + for (uint i = 0; i < ethPrices.length; i++) { + wethUsdValueOverTime.add( + block.timestamp + (i * _prizePool.drawPeriodSeconds), + convert(int(ethPrices[i] * 10**USD_DECIMALS)).div(convert(1e18)) + ); + } + } aprOverTime = new UintOverTime(); uint[] memory aprs = vm.parseJsonUintArray(config, "$.simulation.apr_for_each_draw"); @@ -136,6 +144,12 @@ contract Config is CommonBase { } + /// @notice Convert USD to WETH. NOTE: USD must be fixed point USD decimals + /// @dev see USD_DECIMALS above + function usdToWeth(uint usdFixedPointDecimals) public view returns (uint256) { + return uint256(convert(convert(int(usdFixedPointDecimals)).div(wethUsdValueOverTime.get(block.timestamp)))); + } + /** * @notice Get Liquidation Pair decay constant. * @dev This is approximately the maximum decay constant, as the CGDA formula requires computing e^(decayConstant * time). diff --git a/src/utils/Logger.sol b/src/utils/Logger.sol index af5785a..8407a5e 100644 --- a/src/utils/Logger.sol +++ b/src/utils/Logger.sol @@ -10,8 +10,12 @@ struct DrawLog { uint8 numberOfTiers; uint256 startDrawReward; uint256 finishDrawReward; + string reserveLiquidationAmountOutUsd; + string reserveLiquidationAmountInUsd; uint256 burnedPool; uint256 apr; + string totalLiquidationAmountOutUsd; + string totalLiquidationAmountInUsd; uint256[11] tierLiquidityRemaining; uint256[11] tierPrizeSizes; string[11] tierPrizeSizesUsd; @@ -25,24 +29,28 @@ contract Logger is CommonBase { constructor(string memory _outputFilepath) { outputFilepath = _outputFilepath; - vm.writeLine(outputFilepath, "Draw id, Number of Tiers, apr, POOL Burned, Start Draw Reward, Finish Draw Reward, tier1LiquidityRemaining, tier2LiquidityRemaining, tier3LiquidityRemaining, tier4LiquidityRemaining, tier5LiquidityRemaining, tier6LiquidityRemaining, tier7LiquidityRemaining, tier8LiquidityRemaining, tier9LiquidityRemaining, tier10LiquidityRemaining, tier11LiquidityRemaining, tier1PrizeSizes, tier2PrizeSizes, tier3PrizeSizes, tier4PrizeSizes, tier5PrizeSizes, tier6PrizeSizes, tier7PrizeSizes, tier8PrizeSizes, tier9PrizeSizes, tier10PrizeSizes, tier11PrizeSizes, tier1PrizeSizesUsd, tier2PrizeSizesUsd, tier3PrizeSizesUsd, tier4PrizeSizesUsd, tier5PrizeSizesUsd, tier6PrizeSizesUsd, tier7PrizeSizesUsd, tier8PrizeSizesUsd, tier9PrizeSizesUsd, tier10PrizeSizesUsd, tier11PrizeSizesUsd, tier1ClaimedPrizes, tier2ClaimedPrizes, tier3ClaimedPrizes, tier4ClaimedPrizes, tier5ClaimedPrizes, tier6ClaimedPrizes, tier7ClaimedPrizes, tier8ClaimedPrizes, tier9ClaimedPrizes, tier10ClaimedPrizes, tier11ClaimedPrizes, tier1ComputedPrizes, tier2ComputedPrizes, tier3ComputedPrizes, tier4ComputedPrizes, tier5ComputedPrizes, tier6ComputedPrizes, tier7ComputedPrizes, tier8ComputedPrizes, tier9ComputedPrizes, tier10ComputedPrizes, tier11ComputedPrizes"); + vm.writeLine(outputFilepath, "Draw id, Number of Tiers, apr, Total Yield Amount Out (usd), Total Liquidation Amount In (usd), Total Reserve Out (usd), Total Pool Burned (usd), POOL Burned, Start Draw Reward, Finish Draw Reward, tier1LiquidityRemaining, tier2LiquidityRemaining, tier3LiquidityRemaining, tier4LiquidityRemaining, tier5LiquidityRemaining, tier6LiquidityRemaining, tier7LiquidityRemaining, tier8LiquidityRemaining, tier9LiquidityRemaining, tier10LiquidityRemaining, tier11LiquidityRemaining, tier1PrizeSizes, tier2PrizeSizes, tier3PrizeSizes, tier4PrizeSizes, tier5PrizeSizes, tier6PrizeSizes, tier7PrizeSizes, tier8PrizeSizes, tier9PrizeSizes, tier10PrizeSizes, tier11PrizeSizes, tier1PrizeSizesUsd, tier2PrizeSizesUsd, tier3PrizeSizesUsd, tier4PrizeSizesUsd, tier5PrizeSizesUsd, tier6PrizeSizesUsd, tier7PrizeSizesUsd, tier8PrizeSizesUsd, tier9PrizeSizesUsd, tier10PrizeSizesUsd, tier11PrizeSizesUsd, tier1ClaimedPrizes, tier2ClaimedPrizes, tier3ClaimedPrizes, tier4ClaimedPrizes, tier5ClaimedPrizes, tier6ClaimedPrizes, tier7ClaimedPrizes, tier8ClaimedPrizes, tier9ClaimedPrizes, tier10ClaimedPrizes, tier11ClaimedPrizes, tier1ComputedPrizes, tier2ComputedPrizes, tier3ComputedPrizes, tier4ComputedPrizes, tier5ComputedPrizes, tier6ComputedPrizes, tier7ComputedPrizes, tier8ComputedPrizes, tier9ComputedPrizes, tier10ComputedPrizes, tier11ComputedPrizes"); } function log(DrawLog memory _log) public { - uint8 size = 61; + uint8 size = 65; string[] memory data = new string[](size); data[0] = vm.toString(_log.drawId); data[1] = vm.toString(_log.numberOfTiers); data[2] = vm.toString(_log.apr); - data[3] = vm.toString(_log.burnedPool); - data[4] = vm.toString(_log.startDrawReward); - data[5] = vm.toString(_log.finishDrawReward); + data[3] = _log.totalLiquidationAmountOutUsd; + data[4] = _log.totalLiquidationAmountInUsd; + data[5] = _log.reserveLiquidationAmountOutUsd; + data[6] = _log.reserveLiquidationAmountInUsd; + data[7] = vm.toString(_log.burnedPool); + data[8] = vm.toString(_log.startDrawReward); + data[9] = vm.toString(_log.finishDrawReward); for (uint8 i = 0; i < 11; i++) { - data[i + 6] = vm.toString(_log.tierLiquidityRemaining[i]); - data[i + 17] = vm.toString(_log.tierPrizeSizes[i]); - data[i + 28] = _log.tierPrizeSizesUsd[i]; - data[i + 39] = vm.toString(_log.claimedPrizes[i]); - data[i + 50] = vm.toString(_log.computedPrizes[i]); + data[i + 10] = vm.toString(_log.tierLiquidityRemaining[i]); + data[i + 21] = vm.toString(_log.tierPrizeSizes[i]); + data[i + 32] = _log.tierPrizeSizesUsd[i]; + data[i + 43] = vm.toString(_log.claimedPrizes[i]); + data[i + 54] = vm.toString(_log.computedPrizes[i]); } string memory result = data[0]; diff --git a/src/utils/Utils.sol b/src/utils/Utils.sol index eafd36a..e8323b9 100644 --- a/src/utils/Utils.sol +++ b/src/utils/Utils.sol @@ -52,10 +52,6 @@ contract Utils is CommonBase { // } // } - function computeGasCostInUsd(SD59x18 ethValueUsd, uint256 gasCostInEth) public view returns (SD59x18) { - return ethValueUsd.mul(convert(int(gasCostInEth))); - } - // Logging // Clears and logs the CSV headers to the file function initOutputFileCsv(string memory csvFile, string memory csvColumns) public { diff --git a/test/agent/ClaimerAgent.t.sol b/test/agent/ClaimerAgent.t.sol index 4584153..5ba8e3f 100644 --- a/test/agent/ClaimerAgent.t.sol +++ b/test/agent/ClaimerAgent.t.sol @@ -30,10 +30,10 @@ contract ClaimerAgentTest is Test { vm.etch(address(claimer), "claimer"); GasConfig memory gasConfig = GasConfig({ - startDrawCostInEth: 0.3 gwei * 152_473, - finishDrawCostInEth: 0.3 gwei * 405_000, - claimCostInEth: 0.3 gwei * 150_000, - liquidationCostInEth: 0.3 gwei * 500_000 + startDrawCostInUsd: 10, + finishDrawCostInUsd: 10, + claimCostInUsd: 10, + liquidationCostInUsd: 10 }); vm.mockCall( diff --git a/test/environment/SingleChain.t.sol b/test/environment/SingleChain.t.sol index 173db16..17c64aa 100644 --- a/test/environment/SingleChain.t.sol +++ b/test/environment/SingleChain.t.sol @@ -21,7 +21,7 @@ import { StdCheats } from "forge-std/StdCheats.sol"; import { Test } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; -import { Config } from "../../src/utils/Config.sol"; +import { Config, USD_DECIMALS } from "../../src/utils/Config.sol"; import { Utils } from "../../src/utils/Utils.sol"; import { DrawLog, Logger } from "../../src/utils/Logger.sol"; @@ -52,22 +52,16 @@ contract SingleChainTest is CommonBase, StdCheats, Test, Utils { mapping(uint24 drawId => DrawLog) public drawLogs; function setUp() public { - console2.log("SingleChain setUp 1"); startTime = block.timestamp + 10000 days; vm.warp(startTime); config = new Config(); config.load(vm.envString("CONFIG")); - console2.log("SingleChain setUp 2"); logger = new Logger(vm.envString("OUTPUT")); initOutputFileCsv(simulatorCsvFile, simulatorCsvColumns); - console2.log("SingleChain setUp 3"); - env = new SingleChainEnvironment(config); -console2.log("SingleChain setUp 4"); claimerAgent = new ClaimerAgent(env); - console2.log("SingleChain setUp 5"); drawAgent = new DrawAgent(env); liquidatorAgent = new LiquidatorAgent(env); } @@ -81,9 +75,11 @@ console2.log("SingleChain setUp 4"); vm.roll(block.number + 2); // Let agents do their thing + uint yield = env.mintYield(); uint apr = env.updateApr(); liquidatorAgent.check(config.wethUsdValueOverTime().get(block.timestamp), config.poolUsdValueOverTime().get(block.timestamp)); - + + uint24 openDrawId = env.prizePool().getOpenDrawId(); uint24 finalizedDrawId = env.prizePool().getLastAwardedDrawId(); DrawLog memory finalizedDrawLog = drawLogs[finalizedDrawId]; finalizedDrawLog.apr = apr; @@ -95,7 +91,11 @@ console2.log("SingleChain setUp 4"); closedDrawLog.numberOfTiers = closedDrawDetail.numberOfTiers; closedDrawLog.startDrawReward = closedDrawDetail.startDrawReward; closedDrawLog.finishDrawReward = closedDrawDetail.finishDrawReward; - closedDrawLog.burnedPool = liquidatorAgent.totalBurnedPoolPerDraw(closedDrawId); + closedDrawLog.totalLiquidationAmountOutUsd = formatUsd(liquidatorAgent.totalAmountOutPerDraw(closedDrawId), config.poolUsdValueOverTime().get(block.timestamp)); + closedDrawLog.totalLiquidationAmountInUsd = formatUsd(liquidatorAgent.totalAmountInPerDraw(closedDrawId), config.wethUsdValueOverTime().get(block.timestamp)); + closedDrawLog.reserveLiquidationAmountInUsd = formatUsd(liquidatorAgent.feeBurnerAmountInPerDraw(closedDrawId), config.poolUsdValueOverTime().get(block.timestamp)); + closedDrawLog.reserveLiquidationAmountOutUsd = formatUsd(liquidatorAgent.feeBurnerAmountOutPerDraw(closedDrawId), config.wethUsdValueOverTime().get(block.timestamp)); + closedDrawLog.burnedPool = liquidatorAgent.feeBurnerAmountInPerDraw(closedDrawId); { for (uint8 t = 0; t < closedDrawLog.numberOfTiers; t++) { @@ -194,10 +194,10 @@ console2.log("SingleChain setUp 4"); console2.log(""); console2.log("Average fee per claim (WETH): ", formatTokens(averageFeePerClaim, config.wethUsdValueOverTime().get(block.timestamp))); console2.log(""); - console2.log("Start draw cost (WETH): ", formatTokens(config.gas().startDrawCostInEth, config.wethUsdValueOverTime().get(block.timestamp))); - console2.log("Award draw cost (WETH): ", formatTokens(config.gas().finishDrawCostInEth, config.wethUsdValueOverTime().get(block.timestamp))); - console2.log("Claim cost (WETH): \t ", formatTokens(config.gas().claimCostInEth, config.wethUsdValueOverTime().get(block.timestamp))); - console2.log("Liq. cost (WETH): \t ", formatTokens(config.gas().liquidationCostInEth, config.wethUsdValueOverTime().get(block.timestamp))); + console2.log("Start draw cost (USD): ", formatUsd(config.gas().startDrawCostInUsd)); + console2.log("Award draw cost (USD): ", formatUsd(config.gas().finishDrawCostInUsd)); + console2.log("Claim cost (USD): \t ", formatUsd(config.gas().claimCostInUsd)); + console2.log("Liq. cost (USD): \t ", formatUsd(config.gas().liquidationCostInUsd)); } function printPrizeSummary() public view { @@ -293,34 +293,24 @@ console2.log("SingleChain setUp 4"); decimalPart = string.concat("0", decimalPart); } - string memory usdCentsPart = ""; - uint256 amountInUSD = uint256(convert(convert(int256(value)).mul(exchangeRate))); - uint256 usdWhole = amountInUSD / (1e2); - uint256 usdCentsWhole = amountInUSD % (1e2); - usdCentsPart = vm.toString(usdCentsWhole); - - // show 2 decimals - while(bytes(usdCentsPart).length < 2) { - usdCentsPart = string.concat("0", usdCentsPart); - } - - return string.concat(wholePart, ".", decimalPart, " ($", vm.toString(usdWhole), ".", usdCentsPart, ")"); + return string.concat(wholePart, ".", decimalPart, " (", formatUsd(value, exchangeRate), ")"); } function formatUsd(uint256 tokens, SD59x18 usdPerToken) public view returns(string memory) { uint256 amountInUSD = uint256(convert(convert(int256(tokens)).mul(usdPerToken))); - uint256 usdWhole = amountInUSD / (1e2); - uint256 usdCentsWhole = amountInUSD % (1e2); + return formatUsd(amountInUSD); + } + + function formatUsd(uint256 amountInUSD) public view returns(string memory) { + uint256 usdWhole = amountInUSD / (10**USD_DECIMALS); + uint256 usdCentsWhole = amountInUSD % (10**USD_DECIMALS); string memory usdCentsPart = vm.toString(usdCentsWhole); - // show 2 decimals - while(bytes(usdCentsPart).length < 2) { + while(bytes(usdCentsPart).length < USD_DECIMALS) { usdCentsPart = string.concat("0", usdCentsPart); } - return string.concat(vm.toString(usdWhole), ".", usdCentsPart); + return string.concat("$", vm.toString(usdWhole), ".", usdCentsPart, " USD"); } - - }