Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WLTH - community strategies, limit-order-single.rain #12

Merged
merged 5 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions strategies/wlth/wlth-limit-order-single.rain
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Limit Order Strategy
# 5 buy and sell targets
# Each target you set buy price and amount and sell price and amount
# 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://rpc.ankr.com/base/8e4cac5728d95471ae55724953c7ae6f19a227ac05146276f09717692b732dae
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: 0xbc203ee43d814ca260b6400b46f2a3362e6bb0306291ced89ba06856626cc548
outputs:
- token: base-wlth
vault-id: 0xbc203ee43d814ca260b6400b46f2a3362e6bb0306291ced89ba06856626cc548
base-wlth-buy:
orderbook: base-community
inputs:
- token: base-wlth
vault-id: 0xaa376e00ebecd7042fccde4feb69390a78001ecea37352f1dab8b3d9023f54f7
outputs:
- token: base-usdc
vault-id: 0xaa376e00ebecd7042fccde4feb69390a78001ecea37352f1dab8b3d9023f54f7

scenarios:
limit-orders:
network: base-community
deployer: base-community
orderbook: base-community
bindings:
# Ask for now, registry in future.
uniswap-words: 0xD6B34F97d4A8Cb38D0544dB241CB3f335866f490
orderbook-subparser: 0x8D96ea3EF24D7123882c51CE4325b89bc0d63f9e
scenarios:
buy:
bindings:
# io-ratio and amount for first order.
io-ratio-1: 35
ouptut-amount-1: 1
scenarios:
prod:
bindings:
plottables: '''plottables-prod'
get-trade-count: '''get-trade-count-prod'
metric:
runs: 1
bindings:
plottables: '''plottables-metric'
get-trade-count: '''get-trade-count-prod'
sell:
bindings:
# io-ratio and amount for first order.
io-ratio-1: 0.02
ouptut-amount-1: 50
scenarios:
prod:
bindings:
plottables: '''plottables-prod'
get-trade-count: '''get-trade-count-prod'
metric:
runs: 1
bindings:
plottables: '''plottables-metric'
get-trade-count: '''get-trade-count-prod'


charts:
base-wlth-buy-metrics:
scenario: limit-orders.buy.metric
metrics:
- label: io-ratio-1
value: 0.3.2
- label: amount-1
value: 0.3.3

base-wlth-sell-metrics:
scenario: limit-orders.sell.metric
metrics:
- label: io-ratio-1
value: 0.3.2
- label: amount-1
value: 0.3.3

deployments:
base-wlth-buy:
scenario: limit-orders.buy.prod
order: base-wlth-buy
base-wlth-sell:
scenario: limit-orders.sell.prod
order: base-wlth-sell
---
#uniswap-words !The subparser for the Uniswap words
#orderbook-subparser !The subparser for the Orderbook words

#io-ratio-1 !IO ratio for first order.
#ouptut-amount-1 !Output amount for first order.

#io-ratio-2 !IO ratio for second order.
#ouptut-amount-2 !Output amount for second order.

#io-ratio-3 !IO ratio for third order.
#ouptut-amount-3 !Output amount for third order.

#io-ratio-4 !IO ratio for fourth order.
#ouptut-amount-4 !Output amount for fourth order.

#io-ratio-5 !IO ratio for fifth order.
#ouptut-amount-5 !Output amount for fifth order.

#count-key "count-key"
#plottables !Binding to plot values.
#get-trade-count !Binding to get trade count.
#test-trade-count !Test trade count for plotting.

#plottables-prod
_ _: ;

#plottables-metric
amount io-ratio: ,
_: io-ratio-1,
_: ouptut-amount-1;

#get-trade-count-prod
trade-count-key: hash(order-hash() count-key),
trade-count: get(trade-count-key);

#get-ratio-amount
trade-count: call<'get-trade-count>(),
ouput-amount: conditions(
equal-to(trade-count 0) ouptut-amount-1
"Max order count"
),
io-ratio: conditions(
equal-to(trade-count 0) io-ratio-1
"Max order count"
);

#calculate-io
using-words-from uniswap-words orderbook-subparser

trade-count
final-amount
final-ratio: call<'get-ratio-amount>(),
:call<'plottables>(final-amount final-ratio);

#handle-io
trade-count-key: hash(order-hash() count-key),
trade-count: get(trade-count-key),
:set(trade-count-key add(trade-count 1));
190 changes: 190 additions & 0 deletions test/wlth/WlthLimitOrderSingleTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// 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 = 16817764;

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 testWlthLimitOrdersSell() public {
IO[] memory inputVaults = new IO[](1);
inputVaults[0] = baseUsdcIo();

IO[] memory outputVaults = new IO[](1);
outputVaults[0] = baseWlthIo();

LibStrategyDeployment.StrategyDeployment memory strategy = LibStrategyDeployment.StrategyDeployment(
getEncodedBuyWlthRoute(address(ARB_INSTANCE)),
getEncodedSellWlthRoute(address(ARB_INSTANCE)),
0,
0,
1e6,
10000e18,
0,
0,
"strategies/wlth/wlth-limit-order-single.rain",
"limit-orders.sell.prod",
"./lib/h20.test-std/lib/rain.orderbook",
"./lib/h20.test-std/lib/rain.orderbook/Cargo.toml",
inputVaults,
outputVaults
);

OrderV2 memory order = addOrderDepositOutputTokens(strategy);

{
vm.recordLogs();
// `arb()` called
takeArbOrder(order, strategy.takerRoute, strategy.inputTokenIndex, strategy.outputTokenIndex);

Vm.Log[] memory entries = vm.getRecordedLogs();
(uint256 strategyAmount, uint256 strategyRatio) = getCalculationContext(entries);

assertEq(strategyRatio, 0.02e18);
assertEq(strategyAmount, 50e18);
}
{
vm.expectRevert("Max order count");
takeArbOrder(order, strategy.takerRoute, strategy.inputTokenIndex, strategy.outputTokenIndex);
}

}

function testWlthLimitOrdersBuy() public {
IO[] memory inputVaults = new IO[](1);
inputVaults[0] = baseWlthIo();

IO[] memory outputVaults = new IO[](1);
outputVaults[0] = baseUsdcIo();

LibStrategyDeployment.StrategyDeployment memory strategy = LibStrategyDeployment.StrategyDeployment(
getEncodedSellWlthRoute(address(ARB_INSTANCE)),
getEncodedBuyWlthRoute(address(ARB_INSTANCE)),
0,
0,
100000e18,
10000e6,
0,
0,
"strategies/wlth/wlth-limit-order-single.rain",
"limit-orders.buy.prod",
"./lib/h20.test-std/lib/rain.orderbook",
"./lib/h20.test-std/lib/rain.orderbook/Cargo.toml",
inputVaults,
outputVaults
);

OrderV2 memory order = addOrderDepositOutputTokens(strategy);

{
moveExternalPrice(
strategy.inputVaults[strategy.inputTokenIndex].token,
strategy.outputVaults[strategy.outputTokenIndex].token,
strategy.makerAmount,
strategy.makerRoute
);
}
{
vm.recordLogs();
// `arb()` called
takeArbOrder(order, strategy.takerRoute, strategy.inputTokenIndex, strategy.outputTokenIndex);

Vm.Log[] memory entries = vm.getRecordedLogs();
(uint256 strategyAmount, uint256 strategyRatio) = getCalculationContext(entries);

assertEq(strategyRatio, 35e18);
assertEq(strategyAmount, 1e18);
}
{
vm.expectRevert("Max order count");
takeArbOrder(order, strategy.takerRoute, strategy.inputTokenIndex, strategy.outputTokenIndex);
}
}

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))));
}

}


Loading