From ae2ababc2b02ffbfb662dde3cb858cb0cbaee02c Mon Sep 17 00:00:00 2001 From: Brendan Asselstine Date: Thu, 14 Mar 2024 10:07:31 -0600 Subject: [PATCH 1/6] Changed usd formatting to three decimals --- src/utils/Config.sol | 8 +++++--- test/environment/SingleChain.t.sol | 23 +++++++---------------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/utils/Config.sol b/src/utils/Config.sol index 3dd43d1..9b2cb73 100644 --- a/src/utils/Config.sol +++ b/src/utils/Config.sol @@ -85,15 +85,17 @@ contract Config is CommonBase { function load(string memory filepath) public { string memory config = vm.readFile(filepath); + uint usdDecimals = 3; + wethUsdValueOverTime = new SD59x18OverTime(); - wethUsdValueOverTime.add(block.timestamp, convert(3000e2).div(convert(1e18))); // USD / WETH + wethUsdValueOverTime.add(block.timestamp, convert(int(3000 * 10**usdDecimals)).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**usdDecimals)).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**usdDecimals))).div(poolUsdValueOverTime.get(block.timestamp)))); _simulation.verbosity = vm.parseJsonUint(config, "$.simulation.verbosity"); _simulation.durationDraws = vm.parseJsonUint(config, "$.simulation.duration_draws"); diff --git a/test/environment/SingleChain.t.sol b/test/environment/SingleChain.t.sol index 173db16..ee56ce0 100644 --- a/test/environment/SingleChain.t.sol +++ b/test/environment/SingleChain.t.sol @@ -293,28 +293,19 @@ 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), " USD)"); } 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); + + uint8 numberOfDecimals = 3; + + uint256 usdWhole = amountInUSD / (10**numberOfDecimals); + uint256 usdCentsWhole = amountInUSD % (10**numberOfDecimals); string memory usdCentsPart = vm.toString(usdCentsWhole); - // show 2 decimals - while(bytes(usdCentsPart).length < 2) { + while(bytes(usdCentsPart).length < numberOfDecimals) { usdCentsPart = string.concat("0", usdCentsPart); } From 58d2c04d61f37ccb4dd07a249b58c7bfa19fc55a Mon Sep 17 00:00:00 2001 From: Brendan Asselstine Date: Sun, 17 Mar 2024 08:51:19 -0500 Subject: [PATCH 2/6] Playing with values --- config/optimism.json | 35 ++++++++--------------------------- scripts/ethereum.sh | 2 +- scripts/optimism.sh | 2 +- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/config/optimism.json b/config/optimism.json index c3f8efb..f53a2e7 100644 --- a/config/optimism.json +++ b/config/optimism.json @@ -1,32 +1,13 @@ { "simulation": { - "num_users": "128", + "num_users": "2", "time_step": "1800", "tvl_usd": "10000000", "verbosity": "1", "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" + "50000000000000000" ] }, @@ -35,9 +16,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" }, @@ -58,9 +39,9 @@ }, "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_eth": "3500000000000", + "award_draw_cost_in_eth": "3500000000000", + "claim_cost_in_eth": "1000000000000", + "liquidation_cost_in_eth": "3500000000000" } } 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 From a5d4ed66d4c66dc03e0ca6ece268efb99d3bac7d Mon Sep 17 00:00:00 2001 From: Brendan Asselstine Date: Sun, 17 Mar 2024 10:12:09 -0500 Subject: [PATCH 3/6] forge install: fixed-liquidator --- .gitmodules | 3 +++ lib/fixed-liquidator | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/fixed-liquidator 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/lib/fixed-liquidator b/lib/fixed-liquidator new file mode 160000 index 0000000..9b3597f --- /dev/null +++ b/lib/fixed-liquidator @@ -0,0 +1 @@ +Subproject commit 9b3597f27d8ef9065ee48aee821aebeec4fe6d6f From 06049671dacd5170ca3ed7eecb00111a48d1f0c6 Mon Sep 17 00:00:00 2001 From: Brendan Asselstine Date: Tue, 19 Mar 2024 08:17:45 -0700 Subject: [PATCH 4/6] updated to match new fixed price algorithm --- config/optimism.json | 38 +++++++++++++++++++--- remappings.txt | 1 + src/agent/LiquidatorAgent.sol | 25 +++++++++----- src/environment/SingleChainEnvironment.sol | 36 ++++++++------------ src/utils/Logger.sol | 24 ++++++++------ test/environment/SingleChain.t.sol | 12 +++---- 6 files changed, 85 insertions(+), 51 deletions(-) diff --git a/config/optimism.json b/config/optimism.json index f53a2e7..3f6fa6d 100644 --- a/config/optimism.json +++ b/config/optimism.json @@ -1,13 +1,43 @@ { "simulation": { "num_users": "2", - "time_step": "1800", - "tvl_usd": "10000000", + "time_step": "300", + "tvl_usd": "1000000", "verbosity": "1", - "duration_draws": "5", + "duration_draws": "30", "apr_for_each_draw" : [ - "50000000000000000" + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "50000000000000000", + "200000000000000000", + "100000000000000000", + "10000000000000000" ] }, 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/src/agent/LiquidatorAgent.sol b/src/agent/LiquidatorAgent.sol index ae25157..67cb9f6 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,15 @@ 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; constructor(SingleChainEnvironment _env) { env = _env; @@ -51,6 +53,8 @@ contract LiquidatorAgent is Utils { uint24 openDrawId = prizePool.getOpenDrawId(); (amountOut, amountIn, profit) = checkLiquidationPair(wethUsdValue, poolUsdValue, wethUsdValue, env.pair()); if (profit.gt(wrap(0))) { + totalAmountInPerDraw[openDrawId] += amountIn; + totalAmountOutPerDraw[openDrawId] += amountOut; // console2.log("draw %s: liquidating %s for %s ", openDrawId, amountOut, amountIn); } (amountOut, amountIn, profit) = checkLiquidationPair(poolUsdValue, wethUsdValue, wethUsdValue, env.feeBurnerPair()); @@ -65,7 +69,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 +78,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 +111,7 @@ contract LiquidatorAgent is Utils { logs[10] = 0; logs[11] = pair.maxAmountOut(); + logUint256ToCsv(liquidatorCsvFile, logs); } } @@ -143,6 +149,9 @@ contract LiquidatorAgent is Utils { uint256 amountOut ) public view returns (SD59x18) { SD59x18 amountOutInUsd = tokenOutValueUsd.mul(convert(int256(amountOut))); + if (amountIn > 57896044618658097711785492504343953926634992332820282019728) { + return wrap(0); + } SD59x18 cost = tokenInValueUsd.mul(convert(int256(amountIn))).add(computeGasCostInUsd(ethValueUsd, env.config().gas().liquidationCostInEth)); return cost.lt(amountOutInUsd) ? amountOutInUsd.sub(cost) : wrap(0); } diff --git a/src/environment/SingleChainEnvironment.sol b/src/environment/SingleChainEnvironment.sol index e0ff01f..8ff0be5 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; @@ -162,10 +164,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 +189,14 @@ 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.001e18 ) ) ); vm.label(address(pair), "VaultLiquidationPair"); - router = LiquidationRouter(address(cgdaRouter)); + router = FixedLiquidationRouter(address(fixedRouter)); vault.setLiquidationPair(address(pair)); feeBurnerPair = ILiquidationPair( @@ -208,13 +205,8 @@ 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 being sold ) ) ); diff --git a/src/utils/Logger.sol b/src/utils/Logger.sol index af5785a..82c593d 100644 --- a/src/utils/Logger.sol +++ b/src/utils/Logger.sol @@ -12,6 +12,8 @@ struct DrawLog { uint256 finishDrawReward; uint256 burnedPool; uint256 apr; + string totalYieldUsd; + string totalLiquidatedUsd; uint256[11] tierLiquidityRemaining; uint256[11] tierPrizeSizes; string[11] tierPrizeSizesUsd; @@ -25,24 +27,26 @@ 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, Total Liquidations, 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 = 63; 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.totalYieldUsd; + data[4] = _log.totalLiquidatedUsd; + data[5] = vm.toString(_log.burnedPool); + data[6] = vm.toString(_log.startDrawReward); + data[7] = 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 + 8] = vm.toString(_log.tierLiquidityRemaining[i]); + data[i + 19] = vm.toString(_log.tierPrizeSizes[i]); + data[i + 30] = _log.tierPrizeSizesUsd[i]; + data[i + 41] = vm.toString(_log.claimedPrizes[i]); + data[i + 52] = vm.toString(_log.computedPrizes[i]); } string memory result = data[0]; diff --git a/test/environment/SingleChain.t.sol b/test/environment/SingleChain.t.sol index ee56ce0..fcdcc61 100644 --- a/test/environment/SingleChain.t.sol +++ b/test/environment/SingleChain.t.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,6 +91,8 @@ console2.log("SingleChain setUp 4"); closedDrawLog.numberOfTiers = closedDrawDetail.numberOfTiers; closedDrawLog.startDrawReward = closedDrawDetail.startDrawReward; closedDrawLog.finishDrawReward = closedDrawDetail.finishDrawReward; + closedDrawLog.totalYieldUsd = formatUsd(liquidatorAgent.totalAmountOutPerDraw(closedDrawId), config.poolUsdValueOverTime().get(block.timestamp)); + closedDrawLog.totalLiquidatedUsd = formatUsd(liquidatorAgent.totalAmountInPerDraw(closedDrawId), config.wethUsdValueOverTime().get(block.timestamp)); closedDrawLog.burnedPool = liquidatorAgent.totalBurnedPoolPerDraw(closedDrawId); { From 299b209df249728b2375b35d4639f4a62230fae4 Mon Sep 17 00:00:00 2001 From: Brendan Asselstine Date: Fri, 22 Mar 2024 13:46:18 -0700 Subject: [PATCH 5/6] Updated to latest fixed liquidator --- lib/fixed-liquidator | 2 +- src/agent/LiquidatorAgent.sol | 6 ++-- src/environment/SingleChainEnvironment.sol | 6 ++-- src/utils/Config.sol | 2 -- src/utils/Logger.sol | 32 ++++++++++++---------- test/environment/SingleChain.t.sol | 8 ++++-- 6 files changed, 32 insertions(+), 24 deletions(-) diff --git a/lib/fixed-liquidator b/lib/fixed-liquidator index 9b3597f..3bac408 160000 --- a/lib/fixed-liquidator +++ b/lib/fixed-liquidator @@ -1 +1 @@ -Subproject commit 9b3597f27d8ef9065ee48aee821aebeec4fe6d6f +Subproject commit 3bac4089d10e9465c87dbee6a036b6cb7440b48f diff --git a/src/agent/LiquidatorAgent.sol b/src/agent/LiquidatorAgent.sol index 67cb9f6..f5109d8 100644 --- a/src/agent/LiquidatorAgent.sol +++ b/src/agent/LiquidatorAgent.sol @@ -34,6 +34,8 @@ contract LiquidatorAgent is Utils { 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; @@ -55,11 +57,11 @@ contract LiquidatorAgent is Utils { if (profit.gt(wrap(0))) { totalAmountInPerDraw[openDrawId] += amountIn; totalAmountOutPerDraw[openDrawId] += amountOut; - // console2.log("draw %s: liquidating %s for %s ", openDrawId, amountOut, amountIn); } (amountOut, amountIn, profit) = checkLiquidationPair(poolUsdValue, wethUsdValue, wethUsdValue, env.feeBurnerPair()); if (profit.gt(wrap(0))) { - totalBurnedPoolPerDraw[openDrawId] += amountIn; + feeBurnerAmountInPerDraw[openDrawId] += amountIn; + feeBurnerAmountOutPerDraw[openDrawId] += amountOut; } } diff --git a/src/environment/SingleChainEnvironment.sol b/src/environment/SingleChainEnvironment.sol index 8ff0be5..322a5d6 100644 --- a/src/environment/SingleChainEnvironment.sol +++ b/src/environment/SingleChainEnvironment.sol @@ -190,7 +190,8 @@ contract SingleChainEnvironment is Utils, StdCheats { address(prizeToken), address(vault), config.prizePool().drawPeriodSeconds / 3, - 0.001e18 + 0.001e18, + 0 // no smoothing ) ) ); @@ -206,7 +207,8 @@ contract SingleChainEnvironment is Utils, StdCheats { address(poolToken), address(prizeToken), config.prizePool().drawPeriodSeconds / 3, - 1e18 // 1 pool being sold + 1e18, // 1 POOL, + 0.95e18 // very high smoothing ) ) ); diff --git a/src/utils/Config.sol b/src/utils/Config.sol index 9b2cb73..cdab408 100644 --- a/src/utils/Config.sol +++ b/src/utils/Config.sol @@ -109,8 +109,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"); diff --git a/src/utils/Logger.sol b/src/utils/Logger.sol index 82c593d..8407a5e 100644 --- a/src/utils/Logger.sol +++ b/src/utils/Logger.sol @@ -10,10 +10,12 @@ struct DrawLog { uint8 numberOfTiers; uint256 startDrawReward; uint256 finishDrawReward; + string reserveLiquidationAmountOutUsd; + string reserveLiquidationAmountInUsd; uint256 burnedPool; uint256 apr; - string totalYieldUsd; - string totalLiquidatedUsd; + string totalLiquidationAmountOutUsd; + string totalLiquidationAmountInUsd; uint256[11] tierLiquidityRemaining; uint256[11] tierPrizeSizes; string[11] tierPrizeSizesUsd; @@ -27,26 +29,28 @@ contract Logger is CommonBase { constructor(string memory _outputFilepath) { outputFilepath = _outputFilepath; - vm.writeLine(outputFilepath, "Draw id, Number of Tiers, apr, Total Yield, Total Liquidations, 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 = 63; + 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] = _log.totalYieldUsd; - data[4] = _log.totalLiquidatedUsd; - data[5] = vm.toString(_log.burnedPool); - data[6] = vm.toString(_log.startDrawReward); - data[7] = 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 + 8] = vm.toString(_log.tierLiquidityRemaining[i]); - data[i + 19] = vm.toString(_log.tierPrizeSizes[i]); - data[i + 30] = _log.tierPrizeSizesUsd[i]; - data[i + 41] = vm.toString(_log.claimedPrizes[i]); - data[i + 52] = 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/test/environment/SingleChain.t.sol b/test/environment/SingleChain.t.sol index fcdcc61..231941e 100644 --- a/test/environment/SingleChain.t.sol +++ b/test/environment/SingleChain.t.sol @@ -91,9 +91,11 @@ contract SingleChainTest is CommonBase, StdCheats, Test, Utils { closedDrawLog.numberOfTiers = closedDrawDetail.numberOfTiers; closedDrawLog.startDrawReward = closedDrawDetail.startDrawReward; closedDrawLog.finishDrawReward = closedDrawDetail.finishDrawReward; - closedDrawLog.totalYieldUsd = formatUsd(liquidatorAgent.totalAmountOutPerDraw(closedDrawId), config.poolUsdValueOverTime().get(block.timestamp)); - closedDrawLog.totalLiquidatedUsd = formatUsd(liquidatorAgent.totalAmountInPerDraw(closedDrawId), config.wethUsdValueOverTime().get(block.timestamp)); - 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++) { From 3dcef000028c3bcd7c5e2948e8e08ec0988c59f2 Mon Sep 17 00:00:00 2001 From: Brendan Asselstine Date: Mon, 25 Mar 2024 12:07:46 -0700 Subject: [PATCH 6/6] Made eth price usd configurable --- config/optimism.json | 54 ++++++---------------- src/agent/ClaimerAgent.sol | 4 +- src/agent/DrawAgent.sol | 6 +-- src/agent/LiquidatorAgent.sol | 3 +- src/environment/SingleChainEnvironment.sol | 3 +- src/utils/Config.sol | 44 ++++++++++++------ src/utils/Utils.sol | 4 -- test/agent/ClaimerAgent.t.sol | 8 ++-- test/environment/SingleChain.t.sol | 27 ++++++----- 9 files changed, 68 insertions(+), 85 deletions(-) diff --git a/config/optimism.json b/config/optimism.json index 3f6fa6d..7074c96 100644 --- a/config/optimism.json +++ b/config/optimism.json @@ -1,43 +1,17 @@ { "simulation": { "num_users": "2", - "time_step": "300", - "tvl_usd": "1000000", + "time_step": "1800", + "tvl_usd": "5000000", "verbosity": "1", + "duration_draws": "6", + + "eth_price_usd_per_draw" : [ + "30" + ], - "duration_draws": "30", "apr_for_each_draw" : [ - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "50000000000000000", - "200000000000000000", - "100000000000000000", - "10000000000000000" + "30000000000000000" ] }, @@ -64,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": "3500000000000", - "award_draw_cost_in_eth": "3500000000000", - "claim_cost_in_eth": "1000000000000", - "liquidation_cost_in_eth": "3500000000000" + "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/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 f5109d8..ac3d503 100644 --- a/src/agent/LiquidatorAgent.sol +++ b/src/agent/LiquidatorAgent.sol @@ -154,7 +154,8 @@ contract LiquidatorAgent is Utils { if (amountIn > 57896044618658097711785492504343953926634992332820282019728) { return wrap(0); } - SD59x18 cost = tokenInValueUsd.mul(convert(int256(amountIn))).add(computeGasCostInUsd(ethValueUsd, env.config().gas().liquidationCostInEth)); + 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 322a5d6..6d85949 100644 --- a/src/environment/SingleChainEnvironment.sol +++ b/src/environment/SingleChainEnvironment.sol @@ -137,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()); @@ -190,7 +191,7 @@ contract SingleChainEnvironment is Utils, StdCheats { address(prizeToken), address(vault), config.prizePool().drawPeriodSeconds / 3, - 0.001e18, + 0.00001e18, 0 // no smoothing ) ) diff --git a/src/utils/Config.sol b/src/utils/Config.sol index cdab408..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,17 +87,12 @@ contract Config is CommonBase { function load(string memory filepath) public { string memory config = vm.readFile(filepath); - uint usdDecimals = 3; - - wethUsdValueOverTime = new SD59x18OverTime(); - wethUsdValueOverTime.add(block.timestamp, convert(int(3000 * 10**usdDecimals)).div(convert(1e18))); // USD / WETH - poolUsdValueOverTime = new SD59x18OverTime(); - poolUsdValueOverTime.add(block.timestamp, convert(int(10**usdDecimals)).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(int(10**usdDecimals))).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"); @@ -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/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 231941e..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"; @@ -194,10 +194,10 @@ contract SingleChainTest is CommonBase, StdCheats, Test, Utils { 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,25 +293,24 @@ contract SingleChainTest is CommonBase, StdCheats, Test, Utils { decimalPart = string.concat("0", decimalPart); } - return string.concat(wholePart, ".", decimalPart, " ($", formatUsd(value, exchangeRate), " USD)"); + 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))); + return formatUsd(amountInUSD); + } - uint8 numberOfDecimals = 3; - - uint256 usdWhole = amountInUSD / (10**numberOfDecimals); - uint256 usdCentsWhole = amountInUSD % (10**numberOfDecimals); + 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); - while(bytes(usdCentsPart).length < numberOfDecimals) { + 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"); } - - }