Skip to content

Commit

Permalink
Merge pull request #12 from h20liquidity/dcatki-community-strategies
Browse files Browse the repository at this point in the history
limit-order-single
  • Loading branch information
Siddharth2207 authored Jul 8, 2024
2 parents 0ac2d09 + 26356f4 commit 05f2c05
Show file tree
Hide file tree
Showing 2 changed files with 375 additions and 0 deletions.
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))));
}

}


0 comments on commit 05f2c05

Please sign in to comment.