From 8a6d1e4c050d1bb6aef24f28e8d194ecb93cb1e5 Mon Sep 17 00:00:00 2001 From: Siddharth2207 Date: Mon, 8 Jul 2024 16:13:59 +0530 Subject: [PATCH] wlth-dca-streaming --- strategies/{wlth => }/dca-streaming.rain | 141 ++++--- strategies/wlth/wlth-dca-streaming.rain | 448 +++++++++++++++++++++++ test/StreamingDcaTest.t.sol | 8 +- test/wlth/WlthStreamingDcaTest.t.sol | 162 ++++++++ 4 files changed, 681 insertions(+), 78 deletions(-) rename strategies/{wlth => }/dca-streaming.rain (80%) create mode 100644 strategies/wlth/wlth-dca-streaming.rain create mode 100644 test/wlth/WlthStreamingDcaTest.t.sol diff --git a/strategies/wlth/dca-streaming.rain b/strategies/dca-streaming.rain similarity index 80% rename from strategies/wlth/dca-streaming.rain rename to strategies/dca-streaming.rain index 92b1cff..994df2b 100644 --- a/strategies/wlth/dca-streaming.rain +++ b/strategies/dca-streaming.rain @@ -1,66 +1,59 @@ # Strategy: Streaming DCA -# Strategy cost averages output token against the input token for an input-ouput token pair, -# buy offering tokens at a fixed rate per unit time which can be provided in the bindings, along with a minimum -# io-ratio for the order. -# Bounty auction to pay for gas denominated in input token terms, with a min and max bounty offered for the trade. -# Since the strategy has a per-second budget, any external order taker can offer any amount of input token and -# take the output tokens from the orderbook provided the trade pays for the gas as well. So even if multiple order -# takers come in and try to take the order, the strategy just cost averages the tokens for a taker and -# calculates the budget amount for next. This prevents external takers to DDos the order as ouput amount is calculated -# for each taker individually. -# -# Target Network: Base -# Quote (Input / Incoming): USDC or WLTH -# Base (Output / Outgoing): WLTH or USDC -# Token contract: https://basescan.org/address/0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D -# Token github: NA -# Liquidity protocol: Uniswap V3 -# Liquidity pool address: https://www.dextools.io/app/en/base/pair-explorer/0x1536ee1506e24e5a36be99c73136cd82907a902e?t=1717921711270 -# Liquidity pool fee: 0.3% +# +# Strategy Description: +# - Strategy cost averages output token against the input token for an input-ouput token pair, +# buy offering tokens at a fixed rate per unit time which can be provided in the bindings, along with a minimum +# io-ratio for the order. +# - Bounty auction to pay for gas denominated in input token terms, with a min and max bounty offered for the trade. +# - Since the strategy has a per-second budget, any external order taker can offer any amount of input token and +# take the output tokens from the orderbook provided the trade pays for the gas as well. So even if multiple order +# takers come in and try to take the order, the strategy just cost averages the tokens for a taker and +# calculates the budget amount for next. This prevents external takers to DDos the order as ouput amount is calculated +# for each taker individually. networks: - base-community: - rpc: https://mainnet.base.org - chain-id: 8453 - network-id: 8453 - currency: ETH + polygon-dolz: + rpc: https://polygon-mainnet.g.alchemy.com/v2/y3BXawVv5uuP_g8BaDlKbKoTBGHo9zD9 + chain-id: 137 + network-id: 137 + currency: MATIC subgraphs: - base-community: https://api.thegraph.com/subgraphs/name/h20liquidity/base-0x2aee87 + polygon-dolz: https://api.thegraph.com/subgraphs/name/h20liquidity/polygon-0xc95a5f8e orderbooks: - base-community: - address: 0x2AeE87D75CD000583DAEC7A28db103B1c0c18b76 - network: base-community - subgraph: base-community + polygon-dolz: + address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 + network: polygon-dolz + subgraph: polygon-dolz deployers: - base-community: - address: 0xfca89cD12Ba1346b1ac570ed988AB43b812733fe - network: base-community + polygon-dolz: + address: 0xB3aC858bEAf7814892d3946A8C109A7D701DF8E7 + network: polygon-dolz tokens: - base-wlth: - network: base-community - address: 0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D - base-usdc: - network: base-community - address: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 + polygon-dolz: + network: polygon-dolz + address: 0x6ab4E20f36ca48B61ECd66c0450fDf665Fa130be + polygon-usdt: + network: polygon-dolz + address: 0xc2132D05D31c914a87C6611C10748AEb04B58e8F orders: # vault-id generated with `openssl rand -hex 32` - polygon-wlth-sell: - orderbook: polygon-wlth + polygon-dolz-sell: + orderbook: polygon-dolz inputs: - token: polygon-usdt vault-id: 0x6049f8ee79b82dd5bc82b368114bb0a69f34d539b04b43208241e1f68da134a8 outputs: - - token: polygon-wlth + - token: polygon-dolz vault-id: 0x6049f8ee79b82dd5bc82b368114bb0a69f34d539b04b43208241e1f68da134a8 - polygon-wlth-buy: - orderbook: polygon-wlth + polygon-dolz-buy: + orderbook: polygon-dolz inputs: - - token: polygon-wlth + - token: polygon-dolz vault-id: 0x6049f8ee79b82dd5bc82b368114bb0a69f34d539b04b43208241e1f68da134a8 outputs: - token: polygon-usdt @@ -68,9 +61,9 @@ orders: scenarios: streaming-dca: - network: base-community - deployer: base-community - orderbook: base-community + network: polygon-dolz + deployer: polygon-dolz + orderbook: polygon-dolz bindings: # Ask for now, registry in future. uniswap-words: 0xbc609623F5020f6Fc7481024862cD5EE3FFf52D7 @@ -81,7 +74,7 @@ scenarios: uniswap-v3-init-code: '[uniswap-v3-init-code]' scenarios: - sell-wlth: + sell-dolz: bindings: # Input and Output token addresses are from perspective of order. input-token-address: 0xc2132D05D31c914a87C6611C10748AEb04B58e8F @@ -89,9 +82,9 @@ scenarios: # If the order's input-output tokens are NOT paired on the uniswap v3 pool, # then the reserve token address is the address of the token which is paired with order's output token on uniswapv3 pool. - # Eg: If WLTH is paired with WETH on the uniswap v3 pool for a USDT-WLTH order, reserve token address is the WETH address. + # Eg: If DOLZ is paired with WETH on the uniswap v3 pool for a USDT-DOLZ order, reserve token address is the WETH address. # If the order's input-output tokens are paired on the uniswap v3 pool, then reserve token address is same as the input token address. - # Eg: For WLTH/USDT pair where USDT is also the order's input token, reserve token address is same as the input token address. + # Eg: For DOLZ/USDT pair where USDT is also the order's input token, reserve token address is same as the input token address. reserve-token-address: 0xc2132D05D31c914a87C6611C10748AEb04B58e8F # Ratio multiplier for calculating the io-ratio. @@ -135,7 +128,7 @@ scenarios: prod: bindings: # Minimum input/output token ratio accepatble for the order. - # Eg: For sell WLTH, min-ratio is the minimum USDT/WLTH value to sell above. + # Eg: For sell DOLZ, min-ratio is the minimum USDT/DOLZ value to sell above. min-ratio: 0.005 plottables: '''plottables-prod' get-last-time: '''get-last-time-prod' @@ -154,7 +147,7 @@ scenarios: get-last-time: '''get-last-time-prod' ensure-ratio: '''ensure-ratio-prod' - buy-wlth: + buy-dolz: bindings: # Input and Output token addresses from perspective of order input-token-address: 0x6ab4E20f36ca48B61ECd66c0450fDf665Fa130be @@ -162,9 +155,9 @@ scenarios: # If the order's input-output tokens are NOT paired on the uniswap v3 pool, # then the reserve token address is the address of the token which is paired with order's output token on uniswapv3 pool. - # Eg: If WLTH is paired with WETH on the uniswap v3 pool for a USDT-WLTH order, reserve token address is the WETH address. + # Eg: If DOLZ is paired with WETH on the uniswap v3 pool for a USDT-DOLZ order, reserve token address is the WETH address. # If the order's input-output tokens are paired on the uniswap v3 pool, then reserve token address is same as the input token address. - # Eg: For WLTH/USDT pair where USDT is also the order's input token, reserve token address is same as the input token address. + # Eg: For DOLZ/USDT pair where USDT is also the order's input token, reserve token address is same as the input token address. reserve-token-address: 0x6ab4E20f36ca48B61ECd66c0450fDf665Fa130be # Ratio multiplier for calculating the io-ratio. @@ -208,7 +201,7 @@ scenarios: prod: bindings: # Minimum input/output token ratio - # Eg: For buy WLTH, min-ratio is the minimum WLTH/USDT value to buy above. + # Eg: For buy DOLZ, min-ratio is the minimum DOLZ/USDT value to buy above. min-ratio: 70 plottables: '''plottables-prod' get-last-time: '''get-last-time-prod' @@ -229,17 +222,17 @@ scenarios: charts: sell-streaming-dca: - scenario: streaming-dca.sell-wlth.chart + scenario: streaming-dca.sell-dolz.chart metrics: - - label: WLTH Per second rate + - label: DOLZ Per second rate value: 0.6.0 - description: Amount of WLTH tokens sold per second. - - label: WLTH sold per hour + description: Amount of DOLZ tokens sold per second. + - label: DOLZ sold per hour value: 0.6.1 - description: Amount of WLTH tokens sold per hour. - - label: WLTH sold per day + description: Amount of DOLZ tokens sold per hour. + - label: DOLZ sold per day value: 0.6.2 - description: Amount of WLTH tokens sold per day. + description: Amount of DOLZ tokens sold per day. - label: Minimum bounty value: 0.6.3 description: Minimum bounty offered in USDT tokens. @@ -258,9 +251,9 @@ charts: value: 0.6.8 sell-dca-simulation: - scenario: streaming-dca.sell-wlth.chart + scenario: streaming-dca.sell-dolz.chart plots: - Number of WLTH tokens sold vs time difference: + Number of DOLZ tokens sold vs time difference: marks: - type: line options: @@ -274,7 +267,7 @@ charts: y: 0.4 buy-streaming-dca: - scenario: streaming-dca.buy-wlth.chart + scenario: streaming-dca.buy-dolz.chart metrics: - label: USDT Per second rate value: 0.6.0 @@ -287,10 +280,10 @@ charts: description: Amount of USDT tokens sold per day. - label: Minimum bounty value: 0.6.3 - description: Minimum bounty offered in WLTH tokens. + description: Minimum bounty offered in DOLZ tokens. - label: Maximum bounty value: 0.6.4 - description: Maximum bounty offered in WLTH tokens. + description: Maximum bounty offered in DOLZ tokens. - label: Bounty auction start value: 0.6.5 description: Number of seconds after which the bounty auction strats after order evals. @@ -303,7 +296,7 @@ charts: value: 0.6.8 buy-dca-simulation: - scenario: streaming-dca.buy-wlth.chart + scenario: streaming-dca.buy-dolz.chart plots: Number of USDT tokens sold vs time difference: marks: @@ -320,12 +313,12 @@ charts: deployments: - base-wlth-dca: - scenario: streaming-dca.sell-wlth.prod - order: polygon-wlth-sell - base-usdc-dca: - scenario: streaming-dca.buy-wlth.prod - order: polygon-wlth-buy + dolz-dca: + scenario: streaming-dca.sell-dolz.prod + order: polygon-dolz-sell + usdt-dca: + scenario: streaming-dca.buy-dolz.prod + order: polygon-dolz-buy --- #input-token-address !Order input token address. #output-token-address !Order output token address. @@ -445,4 +438,4 @@ deployments: :call<'plottables>(); #handle-io - :; + :; \ No newline at end of file diff --git a/strategies/wlth/wlth-dca-streaming.rain b/strategies/wlth/wlth-dca-streaming.rain new file mode 100644 index 0000000..330617f --- /dev/null +++ b/strategies/wlth/wlth-dca-streaming.rain @@ -0,0 +1,448 @@ +# Strategy: Streaming DCA +# Strategy cost averages output token against the input token for an input-ouput token pair, +# buy offering tokens at a fixed rate per unit time which can be provided in the bindings, along with a minimum +# io-ratio for the order. +# Bounty auction to pay for gas denominated in input token terms, with a min and max bounty offered for the trade. +# Since the strategy has a per-second budget, any external order taker can offer any amount of input token and +# take the output tokens from the orderbook provided the trade pays for the gas as well. So even if multiple order +# takers come in and try to take the order, the strategy just cost averages the tokens for a taker and +# calculates the budget amount for next. This prevents external takers to DDos the order as ouput amount is calculated +# for each taker individually. +# +# Target Network: Base +# Quote (Input / Incoming): USDC or WLTH +# Base (Output / Outgoing): WLTH or USDC +# Token contract: https://basescan.org/address/0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D +# Token github: NA +# Liquidity protocol: Uniswap V3 +# Liquidity pool address: https://www.dextools.io/app/en/base/pair-explorer/0x1536ee1506e24e5a36be99c73136cd82907a902e?t=1717921711270 +# Liquidity pool fee: 0.3% + +networks: + base-community: + rpc: https://mainnet.base.org + chain-id: 8453 + network-id: 8453 + currency: ETH + +subgraphs: + base-community: https://api.thegraph.com/subgraphs/name/h20liquidity/base-0x2aee87 + +orderbooks: + base-community: + address: 0x2AeE87D75CD000583DAEC7A28db103B1c0c18b76 + network: base-community + subgraph: base-community + +deployers: + base-community: + address: 0x56394785a22b3BE25470a0e03eD9E0a939C47b9b + network: base-community + +tokens: + base-wlth: + network: base-community + address: 0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D + base-usdc: + network: base-community + address: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 + +orders: + # vault-id generated with `openssl rand -hex 32` + base-wlth-sell: + orderbook: base-community + inputs: + - token: base-usdc + vault-id: 0x10a99da34ba197357c7799dc2b97088ca7ae48d7e89ced420cc6f9f7247373ab + outputs: + - token: base-wlth + vault-id: 0x10a99da34ba197357c7799dc2b97088ca7ae48d7e89ced420cc6f9f7247373ab + base-wlth-buy: + orderbook: base-community + inputs: + - token: base-wlth + vault-id: 0x653455b2594761c14979e694b92c26a9a196230d66496d337aabdbad8a185c96 + outputs: + - token: base-usdc + vault-id: 0x653455b2594761c14979e694b92c26a9a196230d66496d337aabdbad8a185c96 + +scenarios: + streaming-dca: + network: base-community + deployer: base-community + orderbook: base-community + bindings: + # Ask for now, registry in future. + uniswap-words: 0xD6B34F97d4A8Cb38D0544dB241CB3f335866f490 + orderbook-subparser: 0x8D96ea3EF24D7123882c51CE4325b89bc0d63f9e + + # Uniswap V3 factory addresses and init code + uniswap-v3-factory: 0x33128a8fC17869897dcE68Ed026d694621f6FDfD + uniswap-v3-init-code: '[uniswap-v3-init-code]' + + scenarios: + sell-wlth: + bindings: + # Input and Output token addresses are from perspective of order. + input-token-address: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 + output-token-address: 0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D + + # If the order's input-output tokens are NOT paired on the uniswap v3 pool, + # then the reserve token address is the address of the token which is paired with order's output token on uniswapv3 pool. + # Eg: If WLTH is paired with WETH on the uniswap v3 pool for a USDT-WLTH order, reserve token address is the WETH address. + # If the order's input-output tokens are paired on the uniswap v3 pool, then reserve token address is same as the input token address. + # Eg: For WLTH/USDT pair where USDT is also the order's input token, reserve token address is same as the input token address. + reserve-token-address: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 + + # Ratio multiplier for calculating the io-ratio. + # If the order's input-output token are paired on the uniswap v3 pool, then set to identity + # If the order's input-output token are NOT paired on the uniswap v3 pool, then set to reserve. + quote-multiplier: '''quote-multiplier-identity' + + # Number of output tokens offered per second. + # Total number of output tokens offered / Total time duration. + # Eg : 100 tokens cost averaged in 1 hours: 100/3600 = 0.027777777777777778 + per-second-rate: 0.277777777777777778 + + # Unix timestamp for strating of the strategy. + # Ideally set it 15 minutes ahead of the whatever the timestamp is while you're deploying the order. + # https://www.epochconverter.com/ + strat-start-time: 1720430887 + + # Bounty amount denominated in input tokens + # + # Minimum bounty offered in input token denominations. + bounty-min: 0.02 + # Maximum bounty offered in input token denominations. + bounty-max: 1 + # Number of seconds after which the bounty auction starts once the order is evaling. + auction-start-time: 300 + # Number of seconds for which bounty auction will last. + auction-duration: 1800 + + # Uniswap v3 pool fees to calcualte budget from the pool. + # Uniswap v3 pool fees of pool which the output token is paired with. + # If the order's input-output tokens are NOT paired on the uniswap v3 pool, then fee is the pool fee for output-reserve token pool. + # If the order's input-output tokens are paired on the uniswap v3 pool, then fee is the pool fee for output-input token pool. + twap-io-fee: '[uniswap-v3-fee-medium]' + + # Uniswap v3 pool fees to calcualte multiplier for the io-ratio. + # If the order's input-output tokens are NOT paired on the uniswap v3 pool, then fee is the pool fee for input-reserve token pool. + # If the order's input-output tokens are paired on the uniswap v3 pool, then this binding is irrelevant. + twap-multiplier-fee: '[uniswap-v3-fee-low]' + + scenarios: + prod: + bindings: + # Minimum input/output token ratio accepatble for the order. + # Eg: For sell WLTH, min-ratio is the minimum USDT/WLTH value to sell above. + min-ratio: 0.01 + plottables: '''plottables-prod' + get-last-time: '''get-last-time-prod' + ensure-ratio: '''ensure-ratio-prod' + chart: + runs: 1000 + bindings: + min-ratio: 0.01 + plottables: '''plottables-plot' + get-last-time: '''get-last-time-plot' + ensure-ratio: '''ensure-ratio-plot' + test: + bindings: + min-ratio: 0.01 + plottables: '''plottables-prod' + get-last-time: '''get-last-time-prod' + ensure-ratio: '''ensure-ratio-prod' + + buy-wlth: + bindings: + # Input and Output token addresses from perspective of order + input-token-address: 0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D + output-token-address: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 + + # If the order's input-output tokens are NOT paired on the uniswap v3 pool, + # then the reserve token address is the address of the token which is paired with order's output token on uniswapv3 pool. + # Eg: If WLTH is paired with WETH on the uniswap v3 pool for a USDT-WLTH order, reserve token address is the WETH address. + # If the order's input-output tokens are paired on the uniswap v3 pool, then reserve token address is same as the input token address. + # Eg: For WLTH/USDT pair where USDT is also the order's input token, reserve token address is same as the input token address. + reserve-token-address: 0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D + + # Ratio multiplier for calculating the io-ratio. + # If the order's input-output token are paired on the uniswap v3 pool, then set to identity + # If the order's input-output token are NOT paired on the uniswap v3 pool, then set to reserve. + quote-multiplier: '''quote-multiplier-identity' + + # Number of output tokens offered per second. + # Total number of output tokens offered / Total time duration. + # Eg : 100 tokens cost averaged in 1 hours: 100/3600 = 0.027777777777777778 + per-second-rate: 0.01 + + # Unix timestamp for strating of the strategy. + # Ideally set it 15 minutes ahead of the whatever the timestamp is while you're deploying the order. + # https://www.epochconverter.com/ + strat-start-time: 1720430887 + + # Bounty amount denominated in input tokens + # + # Minimum bounty offered in input token denominations. + bounty-min: 1.77 + # Maximum bounty offered in input token denominations. + bounty-max: 88 + # Number of seconds after which the bounty auction starts once the order is evaling. + auction-start-time: 300 + # Number of seconds for which bounty auction will last. + auction-duration: 1800 + + # Uniswap v3 pool fees to calcualte budget from the pool. + # Uniswap v3 pool fees of pool which the output token is paired with. + # If the order's input-output tokens are NOT paired on the uniswap v3 pool, then fee is the pool fee for output-reserve token pool. + # If the order's input-output tokens are paired on the uniswap v3 pool, then fee is the pool fee for output-input token pool. + twap-io-fee: '[uniswap-v3-fee-medium]' + + # Uniswap v3 pool fees to calcualte multiplier for the io-ratio. + # If the order's input-output tokens are NOT paired on the uniswap v3 pool, then fee is the pool fee for input-reserve token pool. + # If the order's input-output tokens are paired on the uniswap v3 pool, then this binding is irrelevant. + twap-multiplier-fee: '[uniswap-v3-fee-low]' + + scenarios: + prod: + bindings: + # Minimum input/output token ratio + # Eg: For buy WLTH, min-ratio is the minimum WLTH/USDT value to buy above. + min-ratio: 20 + plottables: '''plottables-prod' + get-last-time: '''get-last-time-prod' + ensure-ratio: '''ensure-ratio-prod' + chart: + runs: 1000 + bindings: + min-ratio: 20 + plottables: '''plottables-plot' + get-last-time: '''get-last-time-plot' + ensure-ratio: '''ensure-ratio-plot' + test: + bindings: + min-ratio: 100 + plottables: '''plottables-prod' + get-last-time: '''get-last-time-prod' + ensure-ratio: '''ensure-ratio-prod' + +charts: + sell-streaming-dca: + scenario: streaming-dca.sell-wlth.chart + metrics: + - label: WLTH Per second rate + value: 0.6.0 + description: Amount of WLTH tokens sold per second. + - label: WLTH sold per hour + value: 0.6.1 + description: Amount of WLTH tokens sold per hour. + - label: WLTH sold per day + value: 0.6.2 + description: Amount of WLTH tokens sold per day. + - label: Minimum bounty + value: 0.6.3 + description: Minimum bounty offered in USDT tokens. + - label: Maximum bounty + value: 0.6.4 + description: Maximum bounty offered in USDT tokens. + - label: Bounty auction start + value: 0.6.5 + description: Number of seconds after which the bounty auction strats after order evals. + - label: Bounty duration + value: 0.6.6 + description: Duration for which the bounty lasts + - label: Minimum ratio + value: 0.6.7 + - label: Strategy start unix timestamp + value: 0.6.8 + + sell-dca-simulation: + scenario: streaming-dca.sell-wlth.chart + plots: + Number of WLTH tokens sold vs time difference: + marks: + - type: line + options: + x: 0.2 + y: 0.3 + Bounty offered vs time difference: + marks: + - type: line + options: + x: 0.2 + y: 0.4 + + buy-streaming-dca: + scenario: streaming-dca.buy-wlth.chart + metrics: + - label: USDT Per second rate + value: 0.6.0 + description: Amount of USDT tokens sold per second. + - label: USDT sold per hour + value: 0.6.1 + description: Amount of USDT tokens sold per hour. + - label: USDT sold per day + value: 0.6.2 + description: Amount of USDT tokens sold per day. + - label: Minimum bounty + value: 0.6.3 + description: Minimum bounty offered in WLTH tokens. + - label: Maximum bounty + value: 0.6.4 + description: Maximum bounty offered in WLTH tokens. + - label: Bounty auction start + value: 0.6.5 + description: Number of seconds after which the bounty auction strats after order evals. + - label: Bounty duration + value: 0.6.6 + description: Duration for which the bounty lasts + - label: Minimum ratio + value: 0.6.7 + - label: Strategy start unix timestamp + value: 0.6.8 + + buy-dca-simulation: + scenario: streaming-dca.buy-wlth.chart + plots: + Number of USDT tokens sold vs time difference: + marks: + - type: line + options: + x: 0.2 + y: 0.3 + Bounty offered vs time difference: + marks: + - type: line + options: + x: 0.2 + y: 0.4 + + +deployments: + base-wlth-dca: + scenario: streaming-dca.sell-wlth.prod + order: base-wlth-sell + base-usdc-dca: + scenario: streaming-dca.buy-wlth.prod + order: base-wlth-buy +--- +#input-token-address !Order input token address. +#output-token-address !Order output token address. +#reserve-token-address !Reserve token address. + +#twap-io-fee !Twap fee for the distribution token pool, paired with either stable token. +#twap-multiplier-fee !Twap fee for io-ratio mulitplier for the pool which distribution token is paired with. +#min-ratio !Minimum input ouput ratio for the order. + +#auction-start-time !Minimum time elapsed before the auction begans. +#auction-duration !Total time for which the auction lasts. +#bounty-min !Minimum bounty to offer for each trade in USD. +#bounty-max !Maximum bounty that can be offered. + +#per-second-rate !The rate of stable denominated distributed tokens distributed per second. +#strat-start-time !Strategy start timestamp +#get-last-time !Binding to get last time and current time +#plottables !Binding for charting metrics. +#ensure-ratio !Binding to enfore minimum io-ratio check. +#quote-multiplier !Binding to calculate multiplier for io-ratio. +#test-current-time !Binding to have test current time. + +#uniswap-words !The subparser for the Uniswap words +#orderbook-subparser !The subparser for the Orderbook words +#uniswap-v3-factory !Uniswap v3 factory. +#uniswap-v3-init-code !Uniswap v3 factory init code. +#last-time-key "last-time-key" + +#bounty-auction + current-time last-time: , + time-since-start: saturating-sub(current-time add(last-time auction-start-time)), + growth-index: if( + greater-than(current-time add(last-time auction-start-time)) + min( + div(time-since-start auction-duration) + 1 + ) + 0 + ), + bounty: min( + linear-growth( + bounty-min + saturating-sub(bounty-max bounty-min) + growth-index + ) + bounty-max + ); + +#get-last-time-plot + current-time: test-current-time, + last-time: sub(current-time mod(current-time 86400)); + +#get-last-time-prod + current-time: now(), + last-time: any( + get(hash(order-hash() last-time-key)) + strat-start-time + ); + +#calculate-budget-input + current-budget: , + output-to-reserve: uniswap-v3-quote-exact-input( + output-token-address reserve-token-address + current-budget + uniswap-v3-factory uniswap-v3-init-code + twap-io-fee + ), + output-to-input: call<'quote-multiplier>(output-to-reserve); + +#plottables-plot + _: per-second-rate, + tokens-per-hour: mul(per-second-rate 3600), + tokens-per-day: mul(per-second-rate 86400), + _: bounty-min, + _: bounty-max, + _: auction-start-time, + _: auction-duration, + _: min-ratio, + _: strat-start-time; + +#plottables-prod + :; + +#ensure-ratio-prod + io-ratio: , + :ensure( + greater-than-or-equal-to(io-ratio min-ratio) + "min ratio" + ); + +#ensure-ratio-plot + io-ratio: ; + +#quote-multiplier-identity + _: ; + +#quote-multiplier-reserve + reserve-amount: , + reserve-to-input: uniswap-v3-quote-exact-input( + reserve-token-address input-token-address + reserve-amount + uniswap-v3-factory uniswap-v3-init-code + twap-multiplier-fee + ); + +#calculate-io + using-words-from uniswap-words orderbook-subparser + + current-time last-time: call<'get-last-time>(), + elapsed-time: saturating-sub(current-time last-time), + current-budget: mul(per-second-rate elapsed-time), + bounty-amount: call<'bounty-auction>(current-time last-time), + input-amount: call<'calculate-budget-input>(current-budget), + max-amount: current-budget, + io-ratio: div(saturating-sub(input-amount bounty-amount) current-budget), + :call<'ensure-ratio>(io-ratio), + :call<'plottables>(); + +#handle-io + :; \ No newline at end of file diff --git a/test/StreamingDcaTest.t.sol b/test/StreamingDcaTest.t.sol index 2b202fc..9f01894 100644 --- a/test/StreamingDcaTest.t.sol +++ b/test/StreamingDcaTest.t.sol @@ -93,7 +93,7 @@ contract DcaOracleUniv3Test is StrategyTests { 100000e18, expectedIoRatio, expectedOutputMax, - "strategies/polygon-streaming-dca.rain", + "strategies/dca-streaming.rain", "streaming-dca.sell-dolz.prod", "./lib/h20.test-std/lib/rain.orderbook", "./lib/h20.test-std/lib/rain.orderbook/Cargo.toml", @@ -127,7 +127,7 @@ contract DcaOracleUniv3Test is StrategyTests { 100000e6, expectedIoRatio, expectedOutputMax, - "strategies/polygon-streaming-dca.rain", + "strategies/dca-streaming.rain", "streaming-dca.buy-dolz.prod", "./lib/h20.test-std/lib/rain.orderbook", "./lib/h20.test-std/lib/rain.orderbook/Cargo.toml", @@ -157,7 +157,7 @@ contract DcaOracleUniv3Test is StrategyTests { 100000e18, 0, 0, - "strategies/polygon-streaming-dca.rain", + "strategies/dca-streaming.rain", "streaming-dca.sell-dolz.test", "./lib/h20.test-std/lib/rain.orderbook", "./lib/h20.test-std/lib/rain.orderbook/Cargo.toml", @@ -190,7 +190,7 @@ contract DcaOracleUniv3Test is StrategyTests { 100000e18, 0, 0, - "strategies/polygon-streaming-dca.rain", + "strategies/dca-streaming.rain", "streaming-dca.sell-dolz.prod", "./lib/h20.test-std/lib/rain.orderbook", "./lib/h20.test-std/lib/rain.orderbook/Cargo.toml", diff --git a/test/wlth/WlthStreamingDcaTest.t.sol b/test/wlth/WlthStreamingDcaTest.t.sol new file mode 100644 index 0000000..67de2cb --- /dev/null +++ b/test/wlth/WlthStreamingDcaTest.t.sol @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; +import {console2, Test} from "forge-std/Test.sol"; + +import { + IOrderBookV3, + IO, + OrderV2, + OrderConfigV2, + TakeOrderConfigV2, + TakeOrdersConfigV2 +} from "rain.orderbook.interface/interface/IOrderBookV3.sol"; +import {IOrderBookV3ArbOrderTaker} from "rain.orderbook.interface/interface/IOrderBookV3ArbOrderTaker.sol"; +import {IParserV1} from "rain.interpreter.interface/interface/IParserV1.sol"; +import {IExpressionDeployerV3} from "rain.interpreter.interface/interface/IExpressionDeployerV3.sol"; +import { EvaluableConfigV3, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV2.sol"; +import {IInterpreterV2,SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV2.sol"; +import {IInterpreterStoreV2} from "rain.interpreter.interface/interface/IInterpreterStoreV2.sol"; +import {StrategyTests, IRouteProcessor, LibStrategyDeployment, LibComposeOrders} from "h20.test-std/StrategyTests.sol"; +import {LibEncodedDispatch} from "rain.interpreter.interface/lib/caller/LibEncodedDispatch.sol"; +import {StateNamespace, LibNamespace, FullyQualifiedNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol"; +import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; +import {SafeERC20, IERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import "h20.test-std/lib/LibProcessStream.sol"; + +uint256 constant VAULT_ID = uint256(keccak256("vault")); + + +/// @dev https://basescan.org/address/0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D +IERC20 constant BASE_WLTH= IERC20(0x99b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D); + +/// @dev https://basescan.org/address/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 +IERC20 constant BASE_USDC = IERC20(0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913); + +function baseWlthIo() pure returns (IO memory) { + return IO(address(BASE_WLTH), 18, VAULT_ID); +} + +function baseUsdcIo() pure returns (IO memory) { + return IO(address(BASE_USDC), 6, VAULT_ID); +} + +contract WlthLimitOrderSingleTest is StrategyTests { + + using SafeERC20 for IERC20; + using Strings for address; + + uint256 constant FORK_BLOCK_NUMBER = 16820770; + + function selectFork() internal { + uint256 fork = vm.createFork(vm.envString("RPC_URL_BASE")); + vm.selectFork(fork); + vm.rollFork(FORK_BLOCK_NUMBER); + } + + function getNamespace() public view returns (FullyQualifiedNamespace) { + return LibNamespace.qualifyNamespace(StateNamespace.wrap(0), address(this)); + } + + function setUp() public { + selectFork(); + + PARSER = IParserV1(0xF836f2746B407136a5bCB515495949B1edB75184); + STORE = IInterpreterStoreV2(0x6E4b01603edBDa617002A077420E98C86595748E); + INTERPRETER = IInterpreterV2(0x379b966DC6B117dD47b5Fc5308534256a4Ab1BCC); + EXPRESSION_DEPLOYER = IExpressionDeployerV3(0x56394785a22b3BE25470a0e03eD9E0a939C47b9b); + ORDERBOOK = IOrderBookV3(0x2AeE87D75CD000583DAEC7A28db103B1c0c18b76); + ARB_INSTANCE = IOrderBookV3ArbOrderTaker(0x199b22ce0c9fD88476cCaA2d2aB253Af38BAE3Ae); + ROUTE_PROCESSOR = IRouteProcessor(address(0x83eC81Ae54dD8dca17C3Dd4703141599090751D1)); + EXTERNAL_EOA = address(0x654FEf5Fb8A1C91ad47Ba192F7AA81dd3C821427); + APPROVED_EOA = address(0x669845c29D9B1A64FFF66a55aA13EB4adB889a88); + ORDER_OWNER = address(0x19f95a84aa1C48A2c6a7B2d5de164331c86D030C); + + EXTERNAL_EOA = address(0x654FEf5Fb8A1C91ad47Ba192F7AA81dd3C821427); + APPROVED_EOA = address(0x669845c29D9B1A64FFF66a55aA13EB4adB889a88); + ORDER_OWNER = address(0x19f95a84aa1C48A2c6a7B2d5de164331c86D030C); + } + + function testWlthSellStreamingDca() public { + + IO[] memory inputVaults = new IO[](1); + inputVaults[0] = baseUsdcIo(); + + IO[] memory outputVaults = new IO[](1); + outputVaults[0] = baseWlthIo(); + + uint256 expectedIoRatio = 0.023931923999999999e18; + uint256 expectedOutputMax = 83.333333333333333400e18; + + LibStrategyDeployment.StrategyDeployment memory strategy = LibStrategyDeployment.StrategyDeployment( + getEncodedBuyWlthRoute(address(ARB_INSTANCE)), + getEncodedSellWlthRoute(address(ARB_INSTANCE)), + 0, + 0, + 1e6, + 10000e18, + expectedIoRatio, + expectedOutputMax, + "strategies/wlth/wlth-dca-streaming.rain", + "streaming-dca.sell-wlth.prod", + "./lib/h20.test-std/lib/rain.orderbook", + "./lib/h20.test-std/lib/rain.orderbook/Cargo.toml", + inputVaults, + outputVaults + ); + + vm.warp(block.timestamp + 300); + // ArbOrderTaker 'arb' + checkStrategyCalculationsArbOrder(strategy); + + } + + function testWlthBuyStreamingDca() public { + + IO[] memory inputVaults = new IO[](1); + inputVaults[0] = baseWlthIo(); + + IO[] memory outputVaults = new IO[](1); + outputVaults[0] = baseUsdcIo(); + + uint256 expectedIoRatio = 40.530791330946428234e18; + uint256 expectedOutputMax = 3e18; + + LibStrategyDeployment.StrategyDeployment memory strategy = LibStrategyDeployment.StrategyDeployment( + getEncodedSellWlthRoute(address(ARB_INSTANCE)), + getEncodedBuyWlthRoute(address(ARB_INSTANCE)), + 0, + 0, + 1e18, + 10000e6, + expectedIoRatio, + expectedOutputMax, + "strategies/wlth/wlth-dca-streaming.rain", + "streaming-dca.buy-wlth.prod", + "./lib/h20.test-std/lib/rain.orderbook", + "./lib/h20.test-std/lib/rain.orderbook/Cargo.toml", + inputVaults, + outputVaults + ); + + vm.warp(block.timestamp + 300); + // ArbOrderTaker 'arb' + checkStrategyCalculationsArbOrder(strategy); + + } + + function getEncodedBuyWlthRoute(address toAddress) internal pure returns (bytes memory) { + bytes memory ROUTE_PRELUDE = + hex"02833589fCD6eDb6E08f4c7C32D4f71b54bdA0291301ffff011536EE1506e24e5A36Be99C73136cD82907A902E01"; + + return abi.encode(bytes.concat(ROUTE_PRELUDE, abi.encodePacked(address(toAddress)))); + } + + function getEncodedSellWlthRoute(address toAddress) internal pure returns (bytes memory) { + bytes memory ROUTE_PRELUDE = + hex"0299b2B1A2aDB02B38222ADcD057783D7e5D1FCC7D01ffff011536EE1506e24e5A36Be99C73136cD82907A902E00"; + + return abi.encode(bytes.concat(ROUTE_PRELUDE, abi.encodePacked(address(toAddress)))); + } + +} +