Skip to content
Closed
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
10 changes: 5 additions & 5 deletions .github/workflows/deploy-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,19 @@ jobs:
echo "IS_PREVIEW=true" >> .env
echo "PREVIEW_ROUNDS=${{ vars.PREVIEW_ROUNDS }}" >> .env
echo "TRACER_SERVICE_NAME=github-preview-${{ github.sha }}" >> .env
echo "RPC_URL=${{ secrets.PREVIEW_RPC_URL }}" >> .env
echo "RPC_URL=${{ secrets.PREVIEW_RPC_URL_V5 }}" >> .env
echo "HYPERDX_API_KEY=${{ secrets.PREVIEW_HYPERDX_API_KEY }}" >> .env
echo "BOT_WALLET_PRIVATEKEY=${{ secrets.PREVIEW_BOT_WALLET_PRIVATEKEY }}" >> .env
echo "MAX_RATIO=${{ vars.PREVIEW_MAX_RATIO }}" >> .env
echo "SUBGRAPH=${{ vars.PREVIEW_SUBGRAPH }}" >> .env
echo "SUBGRAPH=${{ vars.PREVIEW_SUBGRAPH_V5 }}" >> .env
echo "LIQUIDITY_PROVIDERS=${{ vars.PREVIEW_LIQUIDITY_PROVIDERS }}" >> .env
echo "ARB_ADDRESS=${{ vars.PREVIEW_ARB_ADDRESS }}" >> .env
echo "GENERIC_ARB_ADDRESS=${{ vars.PREVIEW_GENERIC_ARB_ADDRESS }}" >> .env
echo "ARB_ADDRESS=${{ vars.PREVIEW_ARB_ADDRESS_V5 }}" >> .env
echo "GENERIC_ARB_ADDRESS=${{ vars.PREVIEW_GENERIC_ARB_ADDRESS_V5 }}" >> .env
echo "BOT_MIN_BALANCE=${{ vars.PREVIEW_BOT_MIN_BALANCE }}" >> .env
echo "GAS_PRICE_MULTIPLIER=${{ vars.PREVIEW_GAS_PRICE_MULTIPLIER }}" >> .env
echo "RP_ONLY=${{ vars.PREVIEW_RP_ONLY }}" >> .env
echo "TX_GAS=${{ vars.PREVIEW_TX_GAS }}" >> .env
echo "DISPAIR=${{ vars.PREVIEW_DISPAIR }}" >> .env
echo "DISPAIR=${{ vars.PREVIEW_DISPAIR_V5 }}" >> .env
echo "CONFIG=.env.config.yaml" >> .env

- name: Run Rain Solver Docker Image
Expand Down
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@opentelemetry/sdk-trace-base": "^1.22.0",
"@opentelemetry/semantic-conventions": "^1.22.0",
"@rainlanguage/dotrain": "^6.0.1-alpha.24",
"@rainlanguage/float": "^0.0.0-alpha.6",
"axios": "^1.3.4",
"commander": "^11.0.0",
"dotenv": "^16.0.3",
Expand Down
15 changes: 15 additions & 0 deletions src/common/abis/deployer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { parseAbi } from "viem";

const _StackItem = `bytes32` as const;
const _SourceIndexV2 = `uint256` as const;
const _FullyQualifiedNamespace = `uint256` as const;
const _EvalV4 =
`(address store, ${_FullyQualifiedNamespace} namespace, bytes bytecode, ${_SourceIndexV2} sourceIndex, bytes32[][] context, ${_StackItem}[] inputs, bytes32[] stateOverlay)` as const;

const _deployer = [
"function parse2(bytes memory data) external view returns (bytes memory bytecode)",
"function iStore() external view returns (address)",
"function iInterpreter() external view returns (address)",
"function iParser() external view returns (address)",
`function eval4(${_EvalV4} calldata eval) external view returns (${_StackItem}[] calldata stack, bytes32[] calldata writes)`,
] as const;

/** Keeps ExpressionDeployer related ABIs */
Expand All @@ -20,4 +27,12 @@ export namespace DeployerAbi {
/** ExpressionDeployerNPE2 signature ABI */
export const deployer = _deployer;
}

/** Deployer and Interpreter structs ABI */
export namespace Structs {
export const EvalV4 = _EvalV4;
export const StackItem = _StackItem;
export const SourceIndexV2 = _SourceIndexV2;
export const FullyQualifiedNamespace = _FullyQualifiedNamespace;
}
}
104 changes: 57 additions & 47 deletions src/common/abis/orderbook.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,54 @@
import { parseAbi } from "viem";
import { parseAbi, parseAbiParameters } from "viem";

// structs
const _IO = "(address token, uint8 decimals, uint256 vaultId)" as const;
const _EvaluableV3 = "(address interpreter, address store, bytes bytecode)" as const;
const _SignedContextV1 = "(address signer, uint256[] context, bytes signature)" as const;
const _TaskV1 = `(${_EvaluableV3} evaluable, ${_SignedContextV1}[] signedContext)` as const;
const _ClearStateChange =
"(uint256 aliceOutput, uint256 bobOutput, uint256 aliceInput, uint256 bobInput)" as const;
const _OrderV3 =
`(address owner, ${_EvaluableV3} evaluable, ${_IO}[] validInputs, ${_IO}[] validOutputs, bytes32 nonce)` as const;
const _TakeOrderConfigV3 =
`(${_OrderV3} order, uint256 inputIOIndex, uint256 outputIOIndex, ${_SignedContextV1}[] signedContext)` as const;
const _OrderConfigV3 =
`(${_EvaluableV3} evaluable, ${_IO}[] validInputs, ${_IO}[] validOutputs, bytes32 nonce, bytes32 secret, bytes meta)` as const;
const _TakeOrdersConfigV3 =
`(uint256 minimumInput, uint256 maximumInput, uint256 maximumIORatio, ${_TakeOrderConfigV3}[] orders, bytes data)` as const;
const _ClearConfig =
"(uint256 aliceInputIOIndex, uint256 aliceOutputIOIndex, uint256 bobInputIOIndex, uint256 bobOutputIOIndex, uint256 aliceBountyVaultId, uint256 bobBountyVaultId)" as const;
const _Quote =
`(${_OrderV3} order, uint256 inputIOIndex, uint256 outputIOIndex, ${_SignedContextV1}[] signedContext)` as const;
const _Float = "bytes32" as const;
const _IOV2 = `(address token, bytes32 vaultId)` as const;
const _EvaluableV4 = `(address interpreter, address store, bytes bytecode)` as const;
const _SignedContextV1 = "(address signer, bytes32[] context, bytes signature)" as const;
const _TaskV2 = `(${_EvaluableV4} evaluable, ${_SignedContextV1}[] signedContext)` as const;
const _ClearStateChangeV2 =
`(${_Float} aliceOutput, ${_Float} bobOutput, ${_Float} aliceInput, ${_Float} bobInput)` as const;
const _OrderV4 =
`(address owner, ${_EvaluableV4} evaluable, ${_IOV2}[] validInputs, ${_IOV2}[] validOutputs, bytes32 nonce)` as const;
const _TakeOrderConfigV4 =
`(${_OrderV4} order, uint256 inputIOIndex, uint256 outputIOIndex, ${_SignedContextV1}[] signedContext)` as const;
const _QuoteV2 =
`(${_OrderV4} order, uint256 inputIOIndex, uint256 outputIOIndex, ${_SignedContextV1}[] signedContext)` as const;
const _TakeOrdersConfigV4 =
`(${_Float} minimumInput, ${_Float} maximumInput, ${_Float} maximumIORatio, ${_TakeOrderConfigV4}[] orders, bytes data)` as const;
const _OrderConfigV4 =
`(${_EvaluableV4} evaluable, ${_IOV2}[] validInputs, ${_IOV2}[] validOutputs, bytes32 nonce, bytes32 secret, bytes meta)` as const;
const _ClearConfigV2 =
"(uint256 aliceInputIOIndex, uint256 aliceOutputIOIndex, uint256 bobInputIOIndex, uint256 bobOutputIOIndex, bytes32 aliceBountyVaultId, bytes32 bobBountyVaultId)" as const;

// signatures
const _Orderbook = [
`event AddOrderV2(address sender, bytes32 orderHash, ${_OrderV3} order)`,
`event RemoveOrderV2(address sender, bytes32 orderHash, ${_OrderV3} order)`,
`event AfterClear(address sender, ${_ClearStateChange} clearStateChange)`,
"function vaultBalance(address owner, address token, uint256 vaultId) external view returns (uint256 balance)",
`function deposit2(address token, uint256 vaultId, uint256 amount, ${_TaskV1}[] calldata tasks) external`,
`function addOrder2(${_OrderConfigV3} calldata config, ${_TaskV1}[] calldata tasks) external returns (bool stateChanged)`,
`function entask(${_TaskV1}[] calldata tasks) external`,
`function withdraw2(address token, uint256 vaultId, uint256 targetAmount, ${_TaskV1}[] calldata tasks) external`,
"function orderExists(bytes32 orderHash) external view returns (bool exists)",
`function removeOrder2(${_OrderV3} calldata order, ${_TaskV1}[] calldata tasks) external returns (bool stateChanged)`,
`event OrderNotFound(address sender, address owner, bytes32 orderHash)` as const,
`event AddOrderV3(address sender, bytes32 orderHash, ${_OrderV4} order)` as const,
`event OrderZeroAmount(address sender, address owner, bytes32 orderHash)` as const,
`event RemoveOrderV3(address sender, bytes32 orderHash, ${_OrderV4} order)` as const,
`event AfterClearV2(address sender, ${_ClearStateChangeV2} clearStateChange)` as const,
`event OrderExceedsMaxRatio(address sender, address owner, bytes32 orderHash)` as const,
`event DepositV2(address sender, address token, bytes32 vaultId, uint256 depositAmountUint256)` as const,
`event ClearV3(address sender, ${_OrderV4} alice, ${_OrderV4} bob, ${_ClearConfigV2} clearConfig)` as const,
`event TakeOrderV3(address sender, ${_TakeOrderConfigV4} config, ${_Float} input, ${_Float} output)` as const,
`event WithdrawV2(address sender, address token, bytes32 vaultId, ${_Float} targetAmount, ${_Float} withdrawAmount, uint256 withdrawAmountUint256)` as const,
`function entask2(${_TaskV2}[] calldata tasks) external` as const,
`function orderExists(bytes32 orderHash) external view returns (bool exists)` as const,
`function vaultBalance2(address owner, address token, bytes32 vaultId) external view returns (${_Float} balance)` as const,
`function deposit3(address token, bytes32 vaultId, ${_Float} depositAmount, ${_TaskV2}[] calldata tasks) external` as const,
`function withdraw3(address token, bytes32 vaultId, ${_Float} targetAmount, ${_TaskV2}[] calldata tasks) external` as const,
`function removeOrder3(${_OrderV4} calldata order, ${_TaskV2}[] calldata tasks) external returns (bool stateChanged)` as const,
`function addOrder3(${_OrderConfigV4} calldata config, ${_TaskV2}[] calldata tasks) external returns (bool stateChanged)` as const,
`function quote2(${_QuoteV2} calldata quoteConfig) external view returns (bool exists, ${_Float} outputMax, ${_Float} ioRatio)` as const,
`function takeOrders3(${_TakeOrdersConfigV4} calldata config) external returns (${_Float} totalTakerInput, ${_Float} totalTakerOutput)` as const,
`function clear3(${_OrderV4} memory alice, ${_OrderV4} memory bob, ${_ClearConfigV2} calldata clearConfig, ${_SignedContextV1}[] memory aliceSignedContext, ${_SignedContextV1}[] memory bobSignedContext) external` as const,
"function multicall(bytes[] calldata data) external returns (bytes[] memory results)",
`function takeOrders2(${_TakeOrdersConfigV3} memory config) external returns (uint256 totalInput, uint256 totalOutput)`,
`function clear2(${_OrderV3} memory aliceOrder, ${_OrderV3} memory bobOrder, ${_ClearConfig} calldata clearConfig, ${_SignedContextV1}[] memory aliceSignedContext, ${_SignedContextV1}[] memory bobSignedContext) external`,
`event TakeOrderV2(address sender, ${_TakeOrderConfigV3} config, uint256 input, uint256 output)`,
`function quote(${_Quote} calldata quoteConfig) external view returns (bool, uint256, uint256)`,
`event ClearV2(address sender, ${_OrderV3} alice, ${_OrderV3} bob, ${_ClearConfig} clearConfig)`,
] as const;
export const _Arb = [
`function arb2(${_TakeOrdersConfigV3} calldata takeOrders, uint256 minimumSenderOutput, ${_EvaluableV3} calldata evaluable) external payable`,
`function arb3(address orderBook, ${_TakeOrdersConfigV3} calldata takeOrders, ${_TaskV1} calldata task) external payable`,
"function iRouteProcessor() external view returns (address)",
`function arb4(address orderBook, ${_TakeOrdersConfigV4} calldata takeOrders, ${_TaskV2} calldata task) external payable`,
`function arb3(address orderBook, ${_TakeOrdersConfigV4} calldata takeOrders, bytes calldata exchangeData, ${_TaskV2} calldata task) external payable`,
] as const;

/** Keeps Orderbook v4 related ABIs */
Expand All @@ -54,21 +60,25 @@ export namespace OrderbookAbi {

/** Orderbook v4 contract ABI */
export const Orderbook = parseAbi(_Orderbook);

/** Order v4 struct ABI */
export const OrderStructAbi = parseAbiParameters(_OrderV4);
}

/** Orderbook v4 structs */
export namespace Structs {
export const IO = _IO;
export const EvaluableV3 = _EvaluableV3;
export const SignedContextV1 = _SignedContextV1;
export const TaskV1 = _TaskV1;
export const ClearStateChange = _ClearStateChange;
export const OrderV3 = _OrderV3;
export const TakeOrderConfigV3 = _TakeOrderConfigV3;
export const OrderConfigV3 = _OrderConfigV3;
export const TakeOrdersConfigV3 = _TakeOrdersConfigV3;
export const ClearConfig = _ClearConfig;
export const Quote = _Quote;
export const Float = _Float;
export const IO = _IOV2;
export const Evaluable = _EvaluableV4;
export const SignedContext = _SignedContextV1;
export const Task = _TaskV2;
export const ClearStateChange = _ClearStateChangeV2;
export const Order = _OrderV4;
export const TakeOrderConfig = _TakeOrderConfigV4;
export const OrderConfig = _OrderConfigV4;
export const TakeOrdersConfig = _TakeOrdersConfigV4;
export const ClearConfig = _ClearConfigV2;
export const Quote = _QuoteV2;
}

/** Signature ABI for Orderbook v4 and Arb contracts */
Expand Down
42 changes: 40 additions & 2 deletions src/common/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
import { withBigintSerializer, sleep, promiseTimeout, shuffleArray, iterRandom } from "./utils";
import { vi, describe, it, expect, beforeEach, afterEach, assert } from "vitest";
import {
sleep,
iterRandom,
shuffleArray,
normalizeFloat,
promiseTimeout,
withBigintSerializer,
toFloat,
} from "./utils";

describe("Test withBigIntSerializer function", async function () {
it("should test withBigIntSerializer", async function () {
Expand Down Expand Up @@ -308,3 +316,33 @@ describe("Test iterRandom function", () => {
expect(iterRandomTime).toBeLessThan(iterShuffleArrayTime);
});
});

describe("Test normalizeFloat", () => {
it("should successfully normalize a valid float hex string", () => {
const result = normalizeFloat(
"0xffffffee00000000000000000000000000000000000000000de0b6b3a7640000",
18,
);

assert(result.isOk());
expect(result.value).toBe(1000000000000000000n);
});

it("should return error when Float.fromHex fails", () => {
const result = normalizeFloat("0xinvalid", 18);

assert(result.isErr());
expect(result.error.readableMsg).toContain("Invalid hex string");
});
});

describe("Test toFloat", () => {
it("should convert bigint to hex float successfully", () => {
const result = toFloat(1000000000000000000n, 18);

assert(result.isOk());
expect(result.value).toBe(
"0xffffffee00000000000000000000000000000000000000000de0b6b3a7640000",
);
});
});
37 changes: 37 additions & 0 deletions src/common/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Float, WasmEncodedError } from "@rainlanguage/float";
import { Result } from "./result";

/**
* Waits for provided miliseconds
* @param ms - Miliseconds to wait
Expand Down Expand Up @@ -77,3 +80,37 @@ export function* iterRandom(array: Array<any>) {
yield array.pop()!; // array pop is also O(1)
}
}

/**
* Normalizes a float value to a fixed number of decimal places
* @param rawFloat - The float value in hex format
* @param decimals - The number of decimal places to normalize to
*/
export function normalizeFloat(
rawFloat: string,
decimals: number,
): Result<bigint, WasmEncodedError> {
const result = Float.fromHex(rawFloat as `0x${string}`);
if (result.error) {
return Result.err(result.error);
}
const fixedResult = result.value.toFixedDecimalLossy(decimals);
if (fixedResult.error) {
return Result.err(fixedResult.error);
}
return Result.ok(fixedResult.value);
}

/**
* Converts a bigint value to a float representation with the specified decimal places
* @param value - The bigint value to convert
* @param decimals - The number of decimal places for the float representation
* @returns The float representation in raw hex string format
*/
export function toFloat(value: bigint, decimals: number): Result<`0x${string}`, WasmEncodedError> {
const result = Float.fromFixedDecimalLossy(value, decimals);
if (result.error) {
return Result.err(result.error);
}
return Result.ok(result.value.asHex());
}
10 changes: 5 additions & 5 deletions src/core/modes/balancer/simulate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Pair } from "../../../order";
import { ABI, Result } from "../../../common";
import { SimulationResult } from "../../types";
import { getEnsureBountyTaskBytecode } from "../../../task";
import { encodeFunctionData, encodeAbiParameters, maxUint256 } from "viem";
import { encodeFunctionData, encodeAbiParameters } from "viem";
import { describe, it, expect, vi, beforeEach, Mock, assert } from "vitest";
import { BalancerRouterError, BalancerRouterErrorType } from "../../../router";
import {
Expand Down Expand Up @@ -200,14 +200,14 @@ describe("Test trySimulateTrade", () => {
// Assert encodeFunctionData was called correctly
expect(encodeFunctionData).toHaveBeenCalledWith({
abi: expect.any(Array), // ArbAbi
functionName: "arb3",
functionName: "arb4",
args: [
"0xorderbook",
{
data: "0xparams",
maximumIORatio: 2000000000000000000n,
maximumInput: maxUint256,
minimumInput: 1n,
maximumIORatio: expect.any(String),
maximumInput: expect.any(String),
minimumInput: expect.any(String),
orders: [{}],
},
{
Expand Down
Loading
Loading