diff --git a/CLAUDE.md b/CLAUDE.md index 6c7184e..a1299ed 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -34,17 +34,17 @@ tests run 2048 iterations. ### Interfaces (`src/interface/`) -- **IRaindexV6** — Current stable interface. Vault-based order book with +- **IRaindexV7** — Current stable interface. Vault-based order book with deposit/withdraw, add/remove orders, take orders (market buy), and clear (match two orders with bounty). IERC3156 flash loan compliant. Supports vaultless orders (vault ID `0` means tokens move directly from wallet) and input/output-based take order limits via `IOIsInput` flag. -- **IRaindexV6OrderTaker / IRaindexV6ArbOrderTaker** — Callback interfaces for +- **IRaindexV7OrderTaker / IRaindexV7ArbOrderTaker** — Callback interfaces for takers receiving tokens during `takeOrders`. - **ierc3156/** — Flash loan interfaces (IERC3156FlashLender, IERC3156FlashBorrower). -- **deprecated/** (v1-v5) — Old interface versions. Do not modify unless - undeprecating. +- **deprecated/** (v1-v6) — Old interface versions. Only import paths may change + (relocation, dependency bumps); declarations are frozen unless undeprecating. ### Interface Lifecycle @@ -63,8 +63,8 @@ move. valid inputs/outputs, nonce - `OrderConfigV4` — Config for adding an order, includes meta and secret - `IOV2` — Input/output config: token address + vault ID -- `TaskV2` — Evaluable + signed context, for post-operation callbacks -- `TakeOrdersConfigV4` / `TakeOrdersConfigV5` — Config for batch taking orders +- `TaskV3` — Evaluable + `SignedContextV2`, for post-operation callbacks +- `TakeOrdersConfigV6` / `TakeOrderConfigV5` — Config for batch taking orders - `ClearConfigV2` / `ClearStateChangeV2` — Config and result for clearing two matched orders @@ -85,8 +85,8 @@ declares everything `rainlang-interface`'s own src imports string messages. - Interfaces use `pragma solidity ^0.8.18` (note: differs from interpreter interface which uses `^0.8.25`). -- Versioned naming: interfaces (`IRaindexV6`), structs (`OrderV4`, - `ClearConfigV2`), events (`AddOrderV3`), functions (`deposit4`, `withdraw4`). +- Versioned naming: interfaces (`IRaindexV7`), structs (`OrderV4`, + `ClearConfigV2`), events (`AddOrderV3`), functions (`deposit5`, `withdraw5`). - Use `//forge-lint: disable-next-line(...)` comments for lint suppressions: `unused-import`, `mixed-case-variable`, `pascal-case-struct`. - Branch naming: `YYYY-MM-DD-description`. diff --git a/foundry.toml b/foundry.toml index 4299174..4720288 100644 --- a/foundry.toml +++ b/foundry.toml @@ -29,7 +29,7 @@ evm_version = "cancun" [dependencies] forge-std = "1.17.0" -"rainlang-interface" = "0.2.13" +"rainlang-interface" = "0.2.14" rain-math-float = "0.3.10" "@openzeppelin-contracts" = "5.7.0" rain-lib-hash = "0.1.27" diff --git a/remappings.txt b/remappings.txt index 90d8ad7..6612fa5 100644 --- a/remappings.txt +++ b/remappings.txt @@ -5,4 +5,4 @@ rain-math-binary-0.1.4/=dependencies/rain-math-binary-0.1.4/ rain-math-float-0.3.10/=dependencies/rain-math-float-0.3.10/ rain-sol-codegen-0.1.39/=dependencies/rain-sol-codegen-0.1.39/ rain-solmem-0.1.28/=dependencies/rain-solmem-0.1.28/ -rainlang-interface-0.2.13/=dependencies/rainlang-interface-0.2.13/ +rainlang-interface-0.2.14/=dependencies/rainlang-interface-0.2.14/ diff --git a/soldeer.lock b/soldeer.lock index d861614..cd5988a 100644 --- a/soldeer.lock +++ b/soldeer.lock @@ -49,7 +49,7 @@ integrity = "e7508cd81a998a67118a0fca314d504dc62850d6b535d29c824f696f214e4b23" [[dependencies]] name = "rainlang-interface" -version = "0.2.13" -url = "https://soldeer-revisions.s3.amazonaws.com/rainlang-interface/0_2_13_11-10-2026_17:54:59_rainlang.zip" -checksum = "8128d2d63ee9c0d83e0ec6f9a5501bdd6da5f21ce3b3374cde2e08eaa4ef1800" -integrity = "07282d9bb019083c64273e829fa4a37016b9c4ddc67578afc7d8e14e235cf021" +version = "0.2.14" +url = "https://soldeer-revisions.s3.amazonaws.com/rainlang-interface/0_2_14_26-10-2026_13:25:43_rainlang.zip" +checksum = "854b90ada2a8756d1c3292fa1272c5630fc0ebf48955bf18f60db9d48e4f210e" +integrity = "d3c5c2983c62b09c3dda643150a3a2a8533c0526fa530b1ded91be69ac64bda5" diff --git a/src/interface/IRaindexV7.sol b/src/interface/IRaindexV7.sol new file mode 100644 index 0000000..8a4ecc9 --- /dev/null +++ b/src/interface/IRaindexV7.sol @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +pragma solidity ^0.8.18; + +import {IERC3156FlashLender} from "./ierc3156/IERC3156FlashLender.sol"; +import { + IInterpreterCallerV5, + SignedContextV2, + EvaluableV4, + + //forge-lint: disable-next-line(unused-import) + IInterpreterV4, + + //forge-lint: disable-next-line(unused-import) + IInterpreterStoreV3 +} from "rainlang-interface-0.2.14/src/interface/IInterpreterCallerV5.sol"; + +import { + ClearStateChangeV2, + ClearConfigV2, + + //forge-lint: disable-next-line(unused-import) + IOV2, + OrderConfigV4, + OrderV4 +} from "./deprecated/v5/IOrderBookV5.sol"; + +import {Float} from "rain-math-float-0.3.10/src/lib/LibDecimalFloat.sol"; + +/// Evaluable run after the primary call, e.g. by governance wrappers or fee +/// collectors. +/// @param evaluable The evaluable logic to run as part of the task. +/// @param signedContext Signed context provided to the evaluable. +struct TaskV3 { + EvaluableV4 evaluable; + SignedContextV2[] signedContext; +} + +/// @param order The order to take. +/// @param inputIOIndex Index of the order's input matched with the taker +/// output. +/// @param outputIOIndex Index of the order's output matched with the taker +/// input. +/// @param signedContext Signed context for the taken order's eval. +struct TakeOrderConfigV5 { + OrderV4 order; + //forge-lint: disable-next-line(mixed-case-variable) + uint256 inputIOIndex; + //forge-lint: disable-next-line(mixed-case-variable) + uint256 outputIOIndex; + SignedContextV2[] signedContext; +} + +/// @param minimumIO Taker's minimum total input or output; reverts if unmet. +/// @param maximumIO Taker's maximum total input or output. +/// @param maximumIORatio Max IO ratio per order, from the order's perspective. +/// @param IOIsInput Whether `minimumIO`/`maximumIO` bound taker input or output. +/// @param orders Taken in sequence as given; no onchain sorting. +/// @param data If non-empty, `onTakeOrders2` is called on the taker with it. +struct TakeOrdersConfigV6 { + //forge-lint: disable-next-line(mixed-case-variable) + Float minimumIO; + //forge-lint: disable-next-line(mixed-case-variable) + Float maximumIO; + //forge-lint: disable-next-line(mixed-case-variable) + Float maximumIORatio; + //forge-lint: disable-next-line(mixed-case-variable) + bool IOIsInput; + TakeOrderConfigV5[] orders; + bytes data; +} + +/// @param order The order to quote. +/// @param inputIOIndex Index of the order's input to quote. +/// @param outputIOIndex Index of the order's output to quote. +/// @param signedContext Signed context for the quoted order's eval. +struct QuoteV3 { + OrderV4 order; + //forge-lint: disable-next-line(mixed-case-variable) + uint256 inputIOIndex; + //forge-lint: disable-next-line(mixed-case-variable) + uint256 outputIOIndex; + SignedContextV2[] signedContext; +} + +/// @title IRaindexV7 +/// @notice Raindex is an order book of expression-defined orders over +/// per-owner, per-token vaults. Amounts and IO ratios (input:output) are +/// Floats, converted via the token's `decimals` only when tokens move; tokens +/// without constant `decimals` are unsupported. Clears move only internal vault +/// balances, except for vault `0` IO. Rounding favours the order. +/// REBASING, FEE-ON-TRANSFER AND OTHER DYNAMIC BALANCE TOKENS ARE NOT +/// SUPPORTED. Raindex ONLY WORKS IF TOKEN BALANCES ARE 1:1 WITH +/// ADDITION/SUBTRACTION PER VAULT MOVEMENT: vaults are credited the requested +/// amount, not the amount received, so a fee-on-transfer deposit credits more +/// than Raindex receives. +/// Orders stay live until removed. Expression storage is namespaced by order +/// owner. Interpreters and stores are untrusted. All vault balances are +/// available as zero-fee ERC3156 flash loans; `withdraw5` and `takeOrders5` +/// repay the caller's loan before sending tokens. Vault ID `0` denotes a +/// vaultless IO that moves tokens directly from or to the owner's wallet. +interface IRaindexV7 is IERC3156FlashLender, IInterpreterCallerV5 { + error ZeroVaultId(address sender, address token); + + error ZeroDepositAmount(address sender, address token, bytes32 vaultId); + + /// Zero requested amount; a nonzero request MAY still move nothing. + error ZeroWithdrawTargetAmount(address sender, address token, bytes32 vaultId); + + error OrderNoSources(); + + error OrderNoHandleIO(); + + error OrderNoInputs(); + + error OrderNoOutputs(); + + error ZeroMaximumIO(); + + error NoOrders(); + + /// An order's input and output tokens are identical. + error TokenSelfTrade(); + + event DepositV2(address sender, address token, bytes32 vaultId, uint256 depositAmountUint256); + + /// @param withdrawAmount MAY be less than `targetAmount`. + /// @param withdrawAmountUint256 Absolute tokens moved onchain. + event WithdrawV2( + address sender, + address token, + bytes32 vaultId, + Float targetAmount, + Float withdrawAmount, + uint256 withdrawAmountUint256 + ); + + /// @param order Full order, to be passed back as-is to take or clear it. + event AddOrderV3(address sender, bytes32 orderHash, OrderV4 order); + + event RemoveOrderV3(address sender, bytes32 orderHash, OrderV4 order); + + /// One per order taken. `input`/`output` are from the taker's perspective. + event TakeOrderV4(address sender, TakeOrderConfigV5 config, Float input, Float output); + + /// The order is skipped rather than reverting the batch. + event OrderNotFound(address sender, address owner, bytes32 orderHash); + + /// The order is skipped rather than reverting the batch. + event OrderZeroAmount(address sender, address owner, bytes32 orderHash); + + /// The order is skipped rather than reverting the batch. + event OrderExceedsMaxRatio(address sender, address owner, bytes32 orderHash); + + /// The order's calculate eval reverted or returned too few outputs. The + /// order is skipped rather than reverting the batch. + event OrderCalculateReverted(address sender, address owner, bytes32 orderHash); + + /// Emitted before calculation. + event ClearV3(address sender, OrderV4 alice, OrderV4 bob, ClearConfigV2 clearConfig); + + event AfterClearV2(address sender, ClearStateChangeV2 clearStateChange); + + function vaultBalance2(address owner, address token, bytes32 vaultId) external view returns (Float balance); + + /// MUST NOT modify vault balances; reverts if any task reverts. + function entask3(TaskV3[] calldata tasks) external; + + /// Deposits for `msg.sender`; no shares, balances are 1:1 with tokens. + /// Reverts `ZeroDepositAmount` on zero amount, `ZeroVaultId` on vault `0`, + /// or if any task reverts. + function deposit5(address token, bytes32 vaultId, Float depositAmount, TaskV3[] calldata tasks) external; + + /// Withdraws up to `targetAmount`. Reverts `ZeroWithdrawTargetAmount` on + /// zero target, `ZeroVaultId` on vault `0`, or if any task reverts. + function withdraw5(address token, bytes32 vaultId, Float targetAmount, TaskV3[] calldata tasks) external; + + function orderExists(bytes32 orderHash) external view returns (bool exists); + + /// Evaluates the order with the caller as counterparty, ignoring the + /// caller's balances. Values are Floats, not absolute token amounts. + /// Reverts `TokenSelfTrade`. `outputMax` and `ioRatio` are `0` if the + /// order does not exist. + function quote3(QuoteV3 calldata quoteConfig) external view returns (bool exists, Float outputMax, Float ioRatio); + + /// Adds an order owned by `msg.sender`. Reverts `OrderNoSources`, + /// `OrderNoHandleIO`, `OrderNoInputs`, `OrderNoOutputs`, or if any task + /// reverts. Calculate MUST return at least max amount and IO ratio. + /// @return stateChanged False, with no state change or event, if the order + /// already exists. + function addOrder5(OrderConfigV4 calldata config, TaskV3[] calldata tasks) external returns (bool stateChanged); + + /// Removes an order owned by `msg.sender`. Reverts if any task reverts. + /// @return stateChanged False, with no state change or event, if the order + /// is not live. + function removeOrder4(OrderV4 calldata order, TaskV3[] calldata tasks) external returns (bool stateChanged); + + /// Takes orders in sequence until `maximumIO` is reached. Per-order + /// failures that depend on live state are skipped with an event; static + /// misconfiguration (e.g. token mismatch, `TokenSelfTrade`) reverts. + /// Reverts if `minimumIO` is not reached. + function takeOrders5(TakeOrdersConfigV6 calldata config) + external + returns (Float totalTakerInput, Float totalTakerOutput); + + /// Matches two live orders from different owners; the ratio spread is paid + /// to `msg.sender`'s vaults per `clearConfig`. Reverts `TokenSelfTrade`, + /// or if either order's input exceeds the other's output. + /// @param aliceSignedContext Signed context for `alice`'s own eval. + /// @param bobSignedContext Signed context for `bob`'s own eval. + function clear4( + OrderV4 memory alice, + OrderV4 memory bob, + ClearConfigV2 calldata clearConfig, + SignedContextV2[] memory aliceSignedContext, + SignedContextV2[] memory bobSignedContext + ) external; +} diff --git a/src/interface/IRaindexV7ArbOrderTaker.sol b/src/interface/IRaindexV7ArbOrderTaker.sol new file mode 100644 index 0000000..31298fb --- /dev/null +++ b/src/interface/IRaindexV7ArbOrderTaker.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +pragma solidity ^0.8.18; + +import {IRaindexV7OrderTaker} from "./IRaindexV7OrderTaker.sol"; +import {TakeOrdersConfigV6, IRaindexV7, TaskV3} from "./IRaindexV7.sol"; + +interface IRaindexV7ArbOrderTaker is IRaindexV7OrderTaker { + /// Takes orders on `raindex` then runs `task`. Implementations MUST + /// validate that `raindex` is trusted. + function arb6(IRaindexV7 raindex, TakeOrdersConfigV6 calldata takeOrders, TaskV3 calldata task) external payable; +} diff --git a/src/interface/IRaindexV7OrderTaker.sol b/src/interface/IRaindexV7OrderTaker.sol new file mode 100644 index 0000000..8a8ded4 --- /dev/null +++ b/src/interface/IRaindexV7OrderTaker.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister +pragma solidity ^0.8.18; + +import {Float} from "./IRaindexV7.sol"; + +interface IRaindexV7OrderTaker { + /// Called by `takeOrders5` when its `data` is non-empty and input is + /// nonzero, after input is sent (net of any flash loan debt) and before + /// output is pulled. Implementations MUST validate `msg.sender` and MUST + /// NOT re-enter the Raindex. + function onTakeOrders2( + address inputToken, + address outputToken, + Float inputAmountSent, + Float totalOutputAmount, + bytes calldata takeOrdersData + ) external; +} diff --git a/src/interface/deprecated/v1/IOrderBookV1.sol b/src/interface/deprecated/v1/IOrderBookV1.sol index befd75d..af4333f 100644 --- a/src/interface/deprecated/v1/IOrderBookV1.sol +++ b/src/interface/deprecated/v1/IOrderBookV1.sol @@ -4,14 +4,14 @@ pragma solidity ^0.8.18; import {IERC3156FlashLender} from "../../ierc3156/IERC3156FlashLender.sol"; //forge-lint: disable-next-line(unused-import) -import {LibEvaluable} from "rainlang-interface-0.2.13/src/lib/caller/LibEvaluable.sol"; +import {LibEvaluable} from "rainlang-interface-0.2.14/src/lib/caller/LibEvaluable.sol"; import { EvaluableConfig, Evaluable, SignedContext, IInterpreterCallerV1 -} from "rainlang-interface-0.2.13/src/interface/deprecated/v1/IInterpreterCallerV1.sol"; -import {IExpressionDeployerV3} from "rainlang-interface-0.2.13/src/interface/deprecated/v1/IExpressionDeployerV3.sol"; +} from "rainlang-interface-0.2.14/src/interface/deprecated/v1/IInterpreterCallerV1.sol"; +import {IExpressionDeployerV3} from "rainlang-interface-0.2.14/src/interface/deprecated/v1/IExpressionDeployerV3.sol"; /// Configuration for a deposit. All deposits are processed by and for /// `msg.sender` so the vaults are unambiguous here. diff --git a/src/interface/deprecated/v2/IOrderBookV2.sol b/src/interface/deprecated/v2/IOrderBookV2.sol index 6b9b44b..d358c34 100644 --- a/src/interface/deprecated/v2/IOrderBookV2.sol +++ b/src/interface/deprecated/v2/IOrderBookV2.sol @@ -6,12 +6,12 @@ import {IERC3156FlashLender} from "../../ierc3156/IERC3156FlashLender.sol"; import { EvaluableConfig, Evaluable -} from "rainlang-interface-0.2.13/src/interface/deprecated/v1/IInterpreterCallerV1.sol"; +} from "rainlang-interface-0.2.14/src/interface/deprecated/v1/IInterpreterCallerV1.sol"; import { SignedContextV1, IInterpreterCallerV2 -} from "rainlang-interface-0.2.13/src/interface/deprecated/v1/IInterpreterCallerV2.sol"; -import {IExpressionDeployerV2} from "rainlang-interface-0.2.13/src/interface/deprecated/v1/IExpressionDeployerV2.sol"; +} from "rainlang-interface-0.2.14/src/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {IExpressionDeployerV2} from "rainlang-interface-0.2.14/src/interface/deprecated/v1/IExpressionDeployerV2.sol"; /// Configuration for a deposit. All deposits are processed by and for /// `msg.sender` so the vaults are unambiguous here. diff --git a/src/interface/deprecated/v3/IOrderBookV3.sol b/src/interface/deprecated/v3/IOrderBookV3.sol index 60ca034..5943653 100644 --- a/src/interface/deprecated/v3/IOrderBookV3.sol +++ b/src/interface/deprecated/v3/IOrderBookV3.sol @@ -8,8 +8,8 @@ import { EvaluableConfigV3, IInterpreterCallerV2, SignedContextV1 -} from "rainlang-interface-0.2.13/src/interface/deprecated/v1/IInterpreterCallerV2.sol"; -import {IExpressionDeployerV3} from "rainlang-interface-0.2.13/src/interface/deprecated/v1/IExpressionDeployerV3.sol"; +} from "rainlang-interface-0.2.14/src/interface/deprecated/v1/IInterpreterCallerV2.sol"; +import {IExpressionDeployerV3} from "rainlang-interface-0.2.14/src/interface/deprecated/v1/IExpressionDeployerV3.sol"; /// Import unmodified structures from older versions of `IOrderBook`. import {IO, ClearConfig, ClearStateChange} from "../v2/IOrderBookV2.sol"; diff --git a/src/interface/deprecated/v4/IOrderBookV4.sol b/src/interface/deprecated/v4/IOrderBookV4.sol index d109d01..0b15d9d 100644 --- a/src/interface/deprecated/v4/IOrderBookV4.sol +++ b/src/interface/deprecated/v4/IOrderBookV4.sol @@ -13,7 +13,7 @@ import { //forge-lint: disable-next-line(unused-import) IInterpreterStoreV2 -} from "rainlang-interface-0.2.13/src/interface/deprecated/v2/IInterpreterCallerV3.sol"; +} from "rainlang-interface-0.2.14/src/interface/deprecated/v2/IInterpreterCallerV3.sol"; /// Import unmodified structures from older versions of `IOrderBook`. import {ClearStateChange, ClearConfig, IO} from "../v3/IOrderBookV3.sol"; diff --git a/src/interface/deprecated/v5/IOrderBookV5.sol b/src/interface/deprecated/v5/IOrderBookV5.sol index 4fbae34..0fb14a2 100644 --- a/src/interface/deprecated/v5/IOrderBookV5.sol +++ b/src/interface/deprecated/v5/IOrderBookV5.sol @@ -13,7 +13,7 @@ import { //forge-lint: disable-next-line(unused-import) IInterpreterStoreV3 -} from "rainlang-interface-0.2.13/src/interface/IInterpreterCallerV4.sol"; +} from "rainlang-interface-0.2.14/src/interface/deprecated/v3/IInterpreterCallerV4.sol"; /// Import unmodified structures from older versions of `IOrderBook`. //forge-lint: disable-start(unused-import) diff --git a/src/interface/IRaindexV6.sol b/src/interface/deprecated/v6/IRaindexV6.sol similarity index 97% rename from src/interface/IRaindexV6.sol rename to src/interface/deprecated/v6/IRaindexV6.sol index e66f93c..2ff6cc0 100644 --- a/src/interface/IRaindexV6.sol +++ b/src/interface/deprecated/v6/IRaindexV6.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 thedavidmeister pragma solidity ^0.8.18; -import {IERC3156FlashLender} from "./ierc3156/IERC3156FlashLender.sol"; +import {IERC3156FlashLender} from "../../ierc3156/IERC3156FlashLender.sol"; import { IInterpreterCallerV4, SignedContextV1, @@ -15,7 +15,7 @@ import { //forge-lint: disable-next-line(unused-import) IInterpreterStoreV3 -} from "rainlang-interface-0.2.13/src/interface/IInterpreterCallerV4.sol"; +} from "rainlang-interface-0.2.14/src/interface/deprecated/v3/IInterpreterCallerV4.sol"; import { ClearStateChangeV2, @@ -28,7 +28,7 @@ import { OrderV4, TakeOrderConfigV4, QuoteV2 -} from "./deprecated/v5/IOrderBookV5.sol"; +} from "../v5/IOrderBookV5.sol"; import {Float} from "rain-math-float-0.3.10/src/lib/LibDecimalFloat.sol"; diff --git a/src/interface/IRaindexV6ArbOrderTaker.sol b/src/interface/deprecated/v6/IRaindexV6ArbOrderTaker.sol similarity index 100% rename from src/interface/IRaindexV6ArbOrderTaker.sol rename to src/interface/deprecated/v6/IRaindexV6ArbOrderTaker.sol diff --git a/src/interface/IRaindexV6OrderTaker.sol b/src/interface/deprecated/v6/IRaindexV6OrderTaker.sol similarity index 100% rename from src/interface/IRaindexV6OrderTaker.sol rename to src/interface/deprecated/v6/IRaindexV6OrderTaker.sol